Files
boc/iom/integrations/arcgis/toolbox.py
T

372 lines
11 KiB
Python
Raw Normal View History

"""
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)}")