# catalog/operations/terrain/slope.yaml

id: terrain_slope
name: Slope
description: >
  Calculate slope from DEM using GDAL DEMProcessing (Horn's method).
  Output is float32 degrees where 0 = flat and 90 = vertical cliff.
version: 2.3.0
category: terrain
type: raster-to-raster
default_implementation: native

inputs:
  - name: dem
    type: raster
    format: cog
    description: Input Digital Elevation Model (GeoTIFF or COG)
    required: true

requires:
  concepts: [elevation]

outputs:
  - name: slope
    type: raster
    format: cog
    dtype: float32
    unit: degrees
    concept: slope
    description: Slope in degrees (0=flat, 90=vertical). NoData from GDAL.

validated_by:
  - "horn-1981"   # Horn (1981), Hill shading and the reflectance map — registry/papers/horn-1981.yaml

params:
  smooth:
    type: boolean
    default: true
    description: Apply Gaussian smoothing to reduce noise
  smooth_sigma:
    type: number
    default: 1.5
    description: "Gaussian sigma (~4-5m radius at 1m resolution)"
    min: 0.1
    max: 10.0
  remove_edges:
    type: boolean
    default: true
    description: Remove edge pixels (reduces tile-boundary artifacts)
  edge_buffer:
    type: integer
    default: 5
    description: Edge buffer size in pixels
    min: 1
    max: 50
  no_data:
    type: integer
    default: 0
    description: NoData value for output

granularity:
  min_resolution_m: 1
  max_resolution_m: 90
  recommended_resolution_m: 10
  output_resolution: inherit
  suitable_aoi_km2:
    min: 0.01
    max: 50000
  realtime_max_km2: 200
  requires_continuous: true

uncertainty:
  error_model: propagated
  factors:
    - name: dem_vertical_accuracy
      description: "Slope error propagates from DEM vertical accuracy"
      severity: medium
      mitigations:
        - "Use higher-accuracy DEM (lidar vs SRTM)"
        - "Apply smoothing for noisy DEMs"
    - name: algorithm_choice
      description: "Horn vs Zevenbergen produce different results on rough terrain"
      severity: low
      mitigations:
        - "Horn for >=10m DEMs, Zevenbergen for <10m"
  limitations:
    - "Assumes square cells in projected CRS"
    - "Edge pixels have reduced accuracy (3x3 kernel)"

execution:
  realtime_max_km2: 200
  cost_per_km2: 0.001
  time_per_km2_sec: 0.5
  memory_profile: low
  profile:
    cpu: low
    memory: low
    io: medium
  scaling:
    model: linear
    parallelizable: true
    min_chunk_km2: 1

default_input:
  connector: usgs_3dep
  params:
    resolution: 1m

# backends: audited 2026-08-14 (defect 50). A key means a runtime that DISPATCHES this op —
# folia-engine `dispatch_op` (products/sdk/folia-engine/src/lib.rs), a `registerOp`/OP_TABLE
# entry in packages/compute, `_BUILTIN_OP_MAP` in folia/compute.py, or a backend manifest
# (folia/backends/*/backend.yaml).
backends:
  rust-wasm:
    function: terrain_ops::terrain_slope
    handle_function: h_terrain_slope
  js:
    function: terrain_slope
  python:
    function: geo.terrain.slope
    dispatch: folia/compute.py _BUILTIN_OP_MAP
  gee:
    function: folia.backends.gee.ops.slope
    dispatch: folia/backends/gee/backend.yaml

display_hints:
  map:
    renderer: maplibre
    palette: terrain
    opacity: 0.8
    rescale: "0,60"
    colormap: viridis
  info:
    fields: [slope_degrees]
    format: "{value}\u00b0"
    section: Terrain

cache_policy:
  regional_precompute: [ski_areas, us_national_forests]
  ttl_days: 90
  invalidate_on: [source_update]
