import os
import subprocess
from pprint import pprint
import sys
import json
import time
import requests
from requests.auth import HTTPBasicAuth
Setup Environment
Set Variables
= 'actinia-gdi'
ACTINIA_USER = 'actinia-gdi'
ACTINIA_PASSWORD = 'actinia-gdi:actinia-gdi'
AUTH = 'v3'
ACTINIA_VERSION = 'http://localhost:8088'
ACTINIA_BASEURL # ACTINIA_BASEURL = 'https://openplains.app/actinia'
= ACTINIA_BASEURL + "/api/" + ACTINIA_VERSION
ACTINIA_URL = HTTPBasicAuth(ACTINIA_USER, ACTINIA_PASSWORD) ACTINIA_AUTH
Setup GRASS Session
sys.path.append("grass", "--config", "python_path"], text=True).strip()
subprocess.check_output([
)# create a temporary folder where to place our GRASS project
import tempfile
from pathlib import Path
= tempfile.TemporaryDirectory()
tempdir
import grass.script as gs
import grass.jupyter as gj
=tempdir.name, name="foss4g2024_p2", epsg="2817", overwrite=True)
gs.create_project(path= gj.init(Path(tempdir.name,"foss4g2024_p2")) session
def print_as_json(data):
print(json.dumps(data, indent=2))
Basic User Limits
LIMITS - max_cell_limit = 2000000 - process_time_limt = 60 - process_num_limit = 20 - number_of_workers = 3
Output formats
- kv: parses the module output and creates key/value pairs
- list: parses the module output and creates a list of values
- table: parses the module output and creates a list of lists with values aka 2D array aka table
Let’s generate a process chain
= {
pc "list": [],
"version": 1
}
From actinia
{
"list": [
{
"module": "g.region",
"id": "g_region_1",
"inputs": [
{
"import_descr": {
"source": "https://storage.googleapis.com/graas-geodata/elev_ned_30m.tif",
"type": "raster"
},
"param": "raster",
"value": "elev_ned_30m_new"
}
],
"flags": "p"
},
{
"module": "r.slope.aspect",
"id": "r_slope_aspect_1",
"inputs": [
{
"param": "elevation",
"value": "elev_ned_30m_new"
}
],
"outputs": [
{
"export": {
"format": "GTiff",
"type": "raster"
},
"param": "slope",
"value": "elev_ned_30m_new_slope"
}
],
"flags": "a"
}
],
"version": "1"
}
!g.region raster=elevation res=30 --json
{
"module": "g.region",
"id": "g.region_1804289383",
"inputs":[
{"param": "raster", "value": "elevation"},
{"param": "res", "value": "30"},
{"param": "format", "value": "plain"}
]}
"general", "region", raster="elevation", res=30) gs.make_command(
['general', '-region', 'raster=elevation', 'res=30', 'json=True']
= !g.region raster=elevation res=30 --json
step_1_raw = ''.join(step_1_raw)
step_1 = json.loads(step_1)
step_1_json pprint(step_1_json)
{'id': 'g.region_1804289383',
'inputs': [{'param': 'raster', 'value': 'elevation'},
{'param': 'res', 'value': '30'},
{'param': 'format', 'value': 'plain'}],
'module': 'g.region'}
= !r.univar map=elevation format="json" --json
step_2_raw = ''.join(step_2_raw)
step_2 = json.loads(step_2)
step_2_json pprint(step_2_json)
{'id': 'r.univar_1804289383',
'inputs': [{'param': 'map', 'value': 'elevation'},
{'param': 'percentile', 'value': '90'},
{'param': 'nprocs', 'value': '1'},
{'param': 'separator', 'value': 'pipe'},
{'param': 'format', 'value': 'json'}],
'module': 'r.univar'}
"list"].append(step_1_json)
pc["list"].append(step_2_json)
pc[
pprint(pc)
{'list': [{'id': 'g.region_1804289383',
'inputs': [{'param': 'raster', 'value': 'elevation'},
{'param': 'res', 'value': '30'},
{'param': 'format', 'value': 'plain'}],
'module': 'g.region'},
{'id': 'r.univar_1804289383',
'inputs': [{'param': 'map', 'value': 'elevation'},
{'param': 'percentile', 'value': '90'},
{'param': 'nprocs', 'value': '1'},
{'param': 'separator', 'value': 'pipe'},
{'param': 'format', 'value': 'json'}],
'module': 'r.univar'}],
'version': 1}
Python Client
Install
!pip install actinia-python-client
!pip install git+https://github.com/openplainsinc/actinia_openapi_python_client.git@v0.0.4
import actinia_openapi_python_client.api_client
from actinia_openapi_python_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
= actinia_openapi_python_client.Configuration(
configuration = "http://localhost:8088"
host
)
# The client must configure the authentication and authorization parameters
# in accordance with the API server security policy.
# Examples for each auth method are provided below, use the example that
# satisfies your auth use case.
# Configure HTTP basic authorization: basicAuth
= actinia_openapi_python_client.Configuration(
configuration = ACTINIA_USER,
username = ACTINIA_PASSWORD
password
)
# Enter a context with an instance of the API client
with actinia_openapi_python_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
= actinia_openapi_python_client.APILogApi(api_client)
api_instance = ACTINIA_USER # str | The unique user name/id
user_id
try:
# Get a list of all API calls that have been called by the provided user.
= api_instance.api_log_user_id_get(user_id)
api_response print("The response of APILogApi->api_log_user_id_get:\n")
pprint(api_response)except ApiException as e:
print("Exception when calling APILogApi->api_log_user_id_get: %s\n" % e)
from actinia import Actinia
= Actinia("http://localhost:8088", "v3")
actinia_dev
actinia_dev.get_version() actinia_dev.set_authentication(ACTINIA_USER, ACTINIA_PASSWORD)
= 'foss4g'
mapset_id = 'nc_spm_08_grass7'
location_id = f"{ACTINIA_URL}/locations/{location_id}/mapsets/{mapset_id}"
url
= requests.post( url, auth=ACTINIA_AUTH)
response
response.json()# pprint(response.json().get('process_results'))
{'accept_datetime': '2024-09-09 20:12:58.748446',
'accept_timestamp': 1725912778.7484446,
'api_info': {'endpoint': 'mapsetmanagementresourceadmin',
'method': 'POST',
'path': '/api/v3/locations/nc_spm_08_grass7/mapsets/foss4g',
'request_url': 'http://localhost:8088/api/v3/locations/nc_spm_08_grass7/mapsets/foss4g'},
'datetime': '2024-09-09 20:12:59.008643',
'http_code': 200,
'message': 'Mapset <foss4g> successfully created.',
'process_chain_list': [{'1': {'flags': 'l', 'module': 'g.mapsets'}}],
'process_log': [{'executable': 'g.mapsets',
'id': '1',
'parameter': ['-l'],
'return_code': 0,
'run_time': 0.05109238624572754,
'stderr': ['Available mapsets:', ''],
'stdout': 'PERMANENT\n'}],
'process_results': {},
'progress': {'num_of_steps': 1, 'step': 1},
'queue': 'local',
'resource_id': 'resource_id-08ec48d8-d82e-436c-b8d0-2cc445ef36a4',
'status': 'finished',
'time_delta': 0.26021814346313477,
'timestamp': 1725912779.008638,
'urls': {'resources': [],
'status': 'https://localhost:8088/api/v3/resources/actinia-gdi/resource_id-08ec48d8-d82e-436c-b8d0-2cc445ef36a4'},
'user_id': 'actinia-gdi'}
= {
pc "list": [
{"id": "computational_region",
"module": "g.region",
"inputs": [
"param": "raster",
{"value": "elevation@PERMANENT"},
"param": "res",
{"value": "10"}
],"stdout": {"id": "region", "format": "kv", "delimiter": "="},
"flags": "g"
},
{"id": "create_hillshading",
"module": "r.relief",
"inputs": [
{"param": "input",
"value": "elevation"
}
],"outputs": [
{"param": "output",
"value": "hillshade"
}
]
},
{"id": "exporter_1",
"module": "exporter",
"outputs": [
{"export": {"type": "raster", "format": "COG"},
"param": "map",
"value": "hillshade"
}
]
}
],"version": "1"
}
= 'foss4g'
mapset_id = 'nc_spm_08_grass7'
location_id = f"{ACTINIA_URL}/locations/{location_id}/processing_async_export"
url
= requests.post(url, auth=ACTINIA_AUTH, json=pc)
response
response
pprint(response.json())= response.json()['urls']['status']
RESPONSE_ID
print("-" * 80)
print(RESPONSE_ID)
{'accept_datetime': '2024-09-09 20:20:05.779403',
'accept_timestamp': 1725913205.7794013,
'api_info': {'endpoint': 'asyncephemeralexportresource',
'method': 'POST',
'path': '/api/v3/locations/nc_spm_08_grass7/processing_async_export',
'request_url': 'http://localhost:8088/api/v3/locations/nc_spm_08_grass7/processing_async_export'},
'datetime': '2024-09-09 20:20:05.782840',
'http_code': 200,
'message': 'Resource accepted',
'process_chain_list': [],
'process_results': {},
'queue': 'local',
'resource_id': 'resource_id-5ceb3125-4ee8-45b5-a13d-8f3b9ba167f3',
'status': 'accepted',
'time_delta': 0.0034470558166503906,
'timestamp': 1725913205.7828374,
'urls': {'resources': [],
'status': 'https://localhost:8088/api/v3/resources/actinia-gdi/resource_id-5ceb3125-4ee8-45b5-a13d-8f3b9ba167f3'},
'user_id': 'actinia-gdi'}
--------------------------------------------------------------------------------
https://localhost:8088/api/v3/resources/actinia-gdi/resource_id-5ceb3125-4ee8-45b5-a13d-8f3b9ba167f3
= requests.get(RESPONSE_ID, auth=ACTINIA_AUTH)
response
pprint(response.json())