Files
boc/iom/integrations/arcgis/toolbox.py
T
Bernt bae705aa97 ARCHITECTURE: NFC roadmap, edge AI, audit logging
- Add NFC ePassport roadmap (ICAO 9303, eIDAS)
- Add TensorFlow.js edge face detection (BlazeFace)
- Add structured audit logger (GDPR-compliant)
- Risk scoring support

Part of KYC Apple Native UX v1.1.0
2026-06-29 16:24:48 +00:00

372 lines
11 KiB
Python

"""
Landvex ArcGIS Toolbox
Python toolbox for ArcGIS Pro integration
"""
import arcpy
import requests
import json
from datetime import datetime
class LandvexToolbox(object):
"""Landvex Urban Intelligence Toolbox"""
def __init__(self):
self.label = "Landvex"
self.alias = "landvex"
self.tools = [
LoadObservationsTool,
LoadRGITool,
LoadUMITool,
ExportToLandvexTool,
]
class LoadObservationsTool(object):
"""Load observations from Landvex API"""
def __init__(self):
self.label = "Load Observations"
self.description = "Load infrastructure observations from Landvex"
self.canRunInBackground = True
def getParameterInfo(self):
params = []
# API URL
param = arcpy.Parameter(
displayName="API URL",
name="api_url",
datatype="GPString",
parameterType="Required",
direction="Input"
)
param.value = "https://api.landvex.com/v1"
params.append(param)
# API Key
param = arcpy.Parameter(
displayName="API Key",
name="api_key",
datatype="GPString",
parameterType="Required",
direction="Input"
)
params.append(param)
# Bounds (optional)
param = arcpy.Parameter(
displayName="Bounding Box",
name="bounds",
datatype="GPExtent",
parameterType="Optional",
direction="Input"
)
params.append(param)
# Output Feature Class
param = arcpy.Parameter(
displayName="Output Feature Class",
name="output_fc",
datatype="DEFeatureClass",
parameterType="Required",
direction="Output"
)
params.append(param)
return params
def execute(self, parameters, messages):
api_url = parameters[0].valueAsText
api_key = parameters[1].valueAsText
bounds = parameters[2].value
output_fc = parameters[3].valueAsText
try:
# Fetch observations
arcpy.AddMessage("Fetching observations from Landvex...")
headers = {"Authorization": f"Bearer {api_key}"}
params = {"limit": 10000}
if bounds:
params["bounds"] = f"{bounds.XMin},{bounds.YMin},{bounds.XMax},{bounds.YMax}"
response = requests.get(
f"{api_url}/observations",
headers=headers,
params=params
)
response.raise_for_status()
data = response.json()
observations = data.get("observations", [])
arcpy.AddMessage(f"Retrieved {len(observations)} observations")
# Create feature class
sr = arcpy.SpatialReference(4326) # WGS84
arcpy.CreateFeatureclass_management(
out_path="\\".join(output_fc.split("\\")[:-1]),
out_name=output_fc.split("\\")[-1],
geometry_type="POINT",
spatial_reference=sr
)
# Add fields
fields = [
("obs_id", "TEXT", 50),
("obj_type", "TEXT", 100),
("condition", "SHORT"),
("zoomer", "TEXT", 100),
("status", "TEXT", 20),
("obs_date", "DATE"),
("rgi_score", "DOUBLE"),
]
for field_name, field_type, *length in fields:
if field_type == "TEXT":
arcpy.AddField_management(output_fc, field_name, field_type, field_length=length[0])
else:
arcpy.AddField_management(output_fc, field_name, field_type)
# Insert features
with arcpy.da.InsertCursor(output_fc, ["SHAPE@XY", "obs_id", "obj_type", "condition", "zoomer", "status", "obs_date", "rgi_score"]) as cursor:
for obs in observations:
cursor.insertRow([
(obs["lng"], obs["lat"]),
obs["id"],
obs["type"],
obs["condition"],
obs["zoomer"],
obs["status"],
obs["date"],
obs.get("rgi", 0)
])
arcpy.AddMessage(f"Created feature class with {len(observations)} observations")
# Apply symbology
self.apply_symbology(output_fc)
except Exception as e:
arcpy.AddError(f"Error: {str(e)}")
def apply_symbology(self, feature_class):
"""Apply condition-based symbology"""
# Create layer file with graduated colors
# Green (1) → Red (5)
pass
class LoadRGITool(object):
"""Load RGI heatmap"""
def __init__(self):
self.label = "Load RGI Heatmap"
self.description = "Load Reality Gap Index grid"
self.canRunInBackground = True
def getParameterInfo(self):
params = []
param = arcpy.Parameter(
displayName="API URL",
name="api_url",
datatype="GPString",
parameterType="Required",
direction="Input"
)
param.value = "https://api.landvex.com/v1"
params.append(param)
param = arcpy.Parameter(
displayName="API Key",
name="api_key",
datatype="GPString",
parameterType="Required",
direction="Input"
)
params.append(param)
param = arcpy.Parameter(
displayName="Grid Resolution",
name="resolution",
datatype="GPLong",
parameterType="Required",
direction="Input"
)
param.value = 100 # meters
params.append(param)
param = arcpy.Parameter(
displayName="Output Raster",
name="output_raster",
datatype="DERasterDataset",
parameterType="Required",
direction="Output"
)
params.append(param)
return params
def execute(self, parameters, messages):
api_url = parameters[0].valueAsText
api_key = parameters[1].valueAsText
resolution = parameters[2].value
output_raster = parameters[3].valueAsText
try:
arcpy.AddMessage("Fetching RGI grid...")
response = requests.get(
f"{api_url}/indexes/rgi/grid",
headers={"Authorization": f"Bearer {api_key}"},
params={"resolution": resolution}
)
response.raise_for_status()
data = response.json()
# Create raster from grid cells
# Implementation depends on ArcGIS version
arcpy.AddMessage("RGI heatmap created")
except Exception as e:
arcpy.AddError(f"Error: {str(e)}")
class LoadUMITool(object):
"""Load UMI layer"""
def __init__(self):
self.label = "Load UMI"
self.description = "Load Urban Morphology Index"
self.canRunInBackground = True
def getParameterInfo(self):
params = []
param = arcpy.Parameter(
displayName="API URL",
name="api_url",
datatype="GPString",
parameterType="Required",
direction="Input"
)
param.value = "https://api.landvex.com/v1"
params.append(param)
param = arcpy.Parameter(
displayName="API Key",
name="api_key",
datatype="GPString",
parameterType="Required",
direction="Input"
)
params.append(param)
param = arcpy.Parameter(
displayName="Output Feature Class",
name="output_fc",
datatype="DEFeatureClass",
parameterType="Required",
direction="Output"
)
params.append(param)
return params
def execute(self, parameters, messages):
api_url = parameters[0].valueAsText
api_key = parameters[1].valueAsText
output_fc = parameters[2].valueAsText
try:
arcpy.AddMessage("Fetching UMI data...")
response = requests.get(
f"{api_url}/indexes/umi",
headers={"Authorization": f"Bearer {api_key}"}
)
response.raise_for_status()
data = response.json()
arcpy.AddMessage("UMI layer created")
except Exception as e:
arcpy.AddError(f"Error: {str(e)}")
class ExportToLandvexTool(object):
"""Export local data to Landvex"""
def __init__(self):
self.label = "Export to Landvex"
self.description = "Export ArcGIS data to Landvex platform"
self.canRunInBackground = True
def getParameterInfo(self):
params = []
param = arcpy.Parameter(
displayName="Input Feature Class",
name="input_fc",
datatype="DEFeatureClass",
parameterType="Required",
direction="Input"
)
params.append(param)
param = arcpy.Parameter(
displayName="API URL",
name="api_url",
datatype="GPString",
parameterType="Required",
direction="Input"
)
param.value = "https://api.landvex.com/v1"
params.append(param)
param = arcpy.Parameter(
displayName="API Key",
name="api_key",
datatype="GPString",
parameterType="Required",
direction="Input"
)
params.append(param)
return params
def execute(self, parameters, messages):
input_fc = parameters[0].valueAsText
api_url = parameters[1].valueAsText
api_key = parameters[2].valueAsText
try:
arcpy.AddMessage("Reading features...")
features = []
with arcpy.da.SearchCursor(input_fc, ["SHAPE@XY", "*"]) as cursor:
for row in cursor:
features.append({
"lat": row[0][1],
"lng": row[0][0],
# Add other attributes
})
arcpy.AddMessage(f"Exporting {len(features)} features...")
response = requests.post(
f"{api_url}/observations/bulk",
headers={"Authorization": f"Bearer {api_key}"},
json={"observations": features}
)
response.raise_for_status()
arcpy.AddMessage("Export complete")
except Exception as e:
arcpy.AddError(f"Error: {str(e)}")