# catalog/operations/analysis/weighted_overlay.yaml

id: analysis_weighted_overlay
name: Weighted Overlay
description: >
  Combine multiple raster layers with configurable weights into a single
  composite/suitability layer. Each input is normalized to a common 0-1 scale
  before weighting. Weights are normalized to sum to 1. Any pixel where any
  input has nodata produces nodata in the output.
version: 1.0.0
category: analysis
type: raster-to-raster
default_implementation: native

inputs:
  - name: rasters
    type: raster[]
    format: geotiff
    description: List of input rasters to combine (must share CRS and dimensions)
    required: true

# Structural: weighted linear combination of any N co-registered rasters.
# Composite/suitability output is recipe-specific. requires: omitted.

outputs:
  - name: composite
    type: raster
    format: cog
    dtype: float32
    description: Weighted composite raster (0-1 range by default)

params:
  weights:
    type: number[]
    required: true
    description: >
      Weights for each input raster. Will be normalized to sum to 1.
      Length must match the number of input rasters.
  normalize_inputs:
    type: boolean
    default: true
    description: >
      Normalize each input to 0-1 range using min-max scaling before
      weighting. Set to false if inputs are already normalized.
  output_range:
    type: number[]
    default: [0.0, 1.0]
    description: Output value range [min, max] for the composite

granularity:
  min_resolution_m: 1
  max_resolution_m: 1000
  recommended_resolution_m: 30
  output_resolution: inherit
  requires_continuous: true
  suitable_aoi_km2:
    min: 0.1
    max: 500000
  realtime_max_km2: 200

uncertainty:
  error_model: multiplicative
  factors:
    - name: weight_subjectivity
      description: "Weights are subjective and significantly affect results"
      severity: high
      mitigations:
        - "Use sensitivity analysis to test weight variations"
        - "Document weight rationale in layer description"
    - name: normalization_artifacts
      description: "Min-max normalization is sensitive to outliers"
      severity: medium
      mitigations:
        - "Pre-clip outliers before overlay"
        - "Use quantile normalization for skewed distributions"
  limitations:
    - "Assumes linear relationship between input values and suitability"
    - "Results are ordinal, not cardinal (relative ranking, not absolute score)"

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

cache_policy:
  ttl_days: 30
  invalidate_on: [source_update, param_change]

# 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:
  python:
    function: geo.raster.weighted_overlay
    dispatch: folia/compute.py _BUILTIN_OP_MAP

display_hints:
  map:
    renderer: maplibre
    palette: viridis
    opacity: 0.8
    rescale: "0,1"
    colormap: viridis
  info:
    fields: [composite_score]
    format: "{value:.2f}"
    section: Analysis

ui:
  icon: layers
  color: "#8B5CF6"
