flowchart LR A[Client] -->|Http Request| B[Actinia REST API] B <--> D[GRASS Processing Node] B -->|Http Response| A
A REST API for GRASS GIS
GRASS is a Geospatial Processing Engine
Open Source (GPL v2)
Developed by International and Multi-institutional groups and individuals (GRASS Development Team)
Member of the Open Source Geospatial Foundation
Received Open Source Security Foundation (OpenSSF) Best Practices Badge - 2024
Import Python Libraries
import os
import subprocess
from pprint import pprint
import sys
import json
import time
from IPython.display import JSON, display
import requests
from requests.auth import HTTPBasicAuthSetup Environment
Deploy Docker container with Actinia
Follow Instructions at : https://github.com/OpenPlainsInc/foss4gna-2024-workshop
Setup Variables
ACTINIA_USER = 'actinia-gdi'
ACTINIA_PASSWORD = 'actinia-gdi'
ACTINIA_VERSION = 'v3'
ACTINIA_BASEURL = 'http://localhost:8089'
ACTINIA_URL = ACTINIA_BASEURL + "/api/" + ACTINIA_VERSION
ACTINIA_AUTH = HTTPBasicAuth(ACTINIA_USER, ACTINIA_PASSWORD)actinia REST API
Tools
Acinia Basics
User Roles
- Superadmin
- Create, modify and delete users
- Read/write access to all databases
- Can access all API calls
- Admin
- All API Calls
- Create, modify and delete users with the maximum user-role user of the same user grou
- Access to persistent databases that were granted by a superadmin
- User
- Can run computational tasks in ephemeral and user specific databases
- Create, modify and delete locations in a user specific database
- Create, modify and delete mapsets in user specific databases
- Limited access to API calls
- Has limited access to persistent databases
- Guest
- Has very limited access to API calls
- Limited access to persistent databases
https://actinia-org.github.io/actinia-core/actinia_concepts/
GRASS Projects
Let’s start by requesting a list of GRASS projects from actinia.
flowchart LR A["/api/v3/locations"]
url = f"{ACTINIA_URL}/locations"
response = requests.get(url, auth=ACTINIA_AUTH)
print_as_json(response.json().get('locations'))Now we will get extra information about a specific project.
flowchart LR
A["/api/v3/locations/"]
A --- C["{location_id}"]
C --- D["/info"]
location_id = 'nc_spm_08'
url = f"{ACTINIA_URL}/locations/{location_id}/info"
response = requests.get( url, auth=ACTINIA_AUTH)
pprint(response.json().get('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 (meter)",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}}
Mapsets
We will now get a list of mapsets for a specific project.
flowchart LR
A["/api/v3/locations/"]
A --- B("{location_id}")
B --- C["/mapsets"]
# mapset = 'nc_spm_08'
location_id = 'nc_spm_08_grass7'
url = f"{ACTINIA_URL}/locations/{location_id}/mapsets"
response = requests.get( url, auth=ACTINIA_AUTH)
pprint(response.json().get('process_results'))None
Now let’s get extra information about a specific mapset PERMANENT.
flowchart LR
A["/api/v3/locations/"]
A --- B("{location_id}")
B --- C["/mapsets/"]
C --- D("{mapset_id}")
D --- E["/info"]
mapset_id = 'PERMANENT'
location_id = 'nc_spm_08_grass7'
url = f"{ACTINIA_URL}/locations/{location_id}/mapsets/{mapset_id}/info"
response = requests.get( url, auth=ACTINIA_AUTH)
pprint(response.json().get('process_results'))None
Layers
Raster Layers
Let’s see all of the mapsets raster layers.
flowchart LR
A["/api/v3/locations/"]
A --- B("{location_id}")
B --- C["/mapsets/"]
C --- D("{mapset_id}")
D --- E["/raster_layers"]
mapset_id = 'PERMANENT'
location_id = 'nc_spm_08_grass7'
url = f"{ACTINIA_URL}/locations/{location_id}/mapsets/{mapset_id}/raster_layers"
response = requests.get( url, auth=ACTINIA_AUTH)
print(response)<Response [404]>
Vector Layers
flowchart LR
A["/api/v3/locations/"]
A --- B("{location_id}")
B --- C["/mapsets/"]
C --- D("{mapset_id}")
D --- E["/vector_layers"]
mapset_id = 'PERMANENT'
location_id = 'nc_spm_08_grass7'
url = f"{ACTINIA_URL}/locations/{location_id}/mapsets/{mapset_id}/vector_layers"
payload = {}
headers = {}
response = requests.get( url, auth=ACTINIA_AUTH, headers=headers)
print(response)<Response [404]>
Processing
Syncronous Processing
Emphemeral process
flowchart LR
A["/api/v3/locations/"]
A --- B("{location_id}")
B --- C["/mapsets/"]
C --- D("{mapset_id}")
D --- E["/processing"]
mapset_id = 'PERMANENT'
location_id = 'nc_spm_08_grass7'
url = f"{ACTINIA_URL}/locations/{location_id}/mapsets/{mapset_id}/processing"
data = {}
response = requests.post( url, auth=ACTINIA_AUTH, json=data)
print(response)<Response [404]>
Asyncronous Processing
flowchart LR
A["/api/v3/locations/"]
A --- B("{location_id}")
B --- C["/mapsets/"]
C --- D("{mapset_id}")
D --- E["/processing_async"]
mapset_id = 'PERMANENT'
location_id = 'nc_spm_08_grass7'
url = f"{ACTINIA_URL}/locations/{location_id}/mapsets/{mapset_id}/processing_async"
data = {}
response = requests.post( url, auth=ACTINIA_AUTH, json=data)
pprint(response.json().get('process_results')){}
Let’s look at the complete API within PostMan or Insomnia.
https://localhost:8080/api/v3/swagger-ui/index.html
Process Chains
Let move on to creating process chains in Part 3.