# Malcomb Climate Vulnerability — Malawi
#
# Reproduction of Malcomb, Weaver & Krakowka (2014):
# "Vulnerability modeling for sub-Saharan Africa: An operationalized
# approach in Malawi." Applied Geography 48:17-30.
#
# Based on the HEGSRR reproduction (Holler, Kedron et al.) at:
# https://github.com/HEGSRR/RPr-Malcomb-2014
#
# Demonstrates multi-criteria weighted overlay vulnerability modeling
# with mixed vector/raster inputs, rasterization of polygon scores,
# and final map algebra composite. Each analytical choice (weights,
# normalization, classification) is an explicit, inspectable parameter.
#
# Pipeline flow:
#
#   source/ta-boundaries ─┐
#   source/dhs-households ─┤
#     (tabular join)       └── capacity/household-scores ──┐
#                              capacity/ta-mean ────────────┤
#                              capacity/ta-raster ──────────┤
#                                                           │
#   source/livelihood-zones ── sensitivity/lhz-scores ──────┤
#                              sensitivity/lhz-raster ──────┤
#                                                           │
#   source/drought-raster ──── exposure/drought-classified ─┤
#   source/flood-raster ────── exposure/flood-classified ───┤
#                                                           │
#   source/lakes ──────────┐                                │
#   source/parks ──────────┤                                │
#     (union + buffer)     └── exclusion/mask-raster ───────┤
#                                                           ▼
#                                       vulnerability/composite
#                                               │
#                                       vulnerability/classified

name: malcomb-vulnerability
version: "1.0"
description: >
  Climate vulnerability model for Malawi reproducing
  Malcomb et al. (2014). Multi-criteria weighted overlay combining
  adaptive capacity (DHS household surveys), livelihood sensitivity
  (FEWS NET zones), and physical exposure (drought + flood risk).

reproduction:
  paper:
    doi: "10.1016/j.apgeog.2014.01.004"
    title: "Vulnerability modeling for sub-Saharan Africa using indicators of adaptive capacity, livelihood sensitivity, and physical exposure"
    authors: ["Malcomb, D. W.", "Weaver, E. A.", "Krakowka, A. R."]
    year: 2014
    journal: "Applied Geography"
    volume: 48
    pages: "17-30"
  lineage:
    - rel: derived-from
      href: "https://github.com/HEGSRR/RPr-Malcomb-2014"
      title: "HEGSRR reproduction (Holler, Kedron et al.)"
  study_period:
    start: "2010-01-01"
    end: "2010-12-31"
  quality_tier: human
  validation_status: unvalidated
  method_ops:
    - raster_rasterize
    - raster_reclassify
    - raster_calc
    - vector_buffer
    - analysis_zonal_stats
  validation:
    comparison: validation/comparison.yaml
    checksums: validation/checksums.yaml

settings:
  default_bbox: [32.5, -17.2, 36.0, -9.3]   # Malawi
  default_crs: EPSG:4326

layers:

  # ============================================================
  # SOURCE LAYERS
  # ============================================================

  source/ta-boundaries:
    uri: data/ta_boundaries.geojson
    type: vector
    description: >
      Traditional Authority (TA) boundaries for Malawi (GADM level 3).
      206 administrative units after cleaning.
    style:
      renderer: maplibre
      stroke: "#555"
      stroke-width: 0.5
      fill-opacity: 0

  source/dhs-households:
    uri: data/dhs_ta_scores.geojson
    type: vector
    description: >
      DHS 2010 household indicators aggregated to TA level.
      12 indicators per TA: livestock, wealth, land, cellphone, radio,
      electricity, cooking fuel, water time, sick in household, orphans,
      female-headed, urban/rural. Pre-aggregated from 17,309 households.
    style:
      renderer: maplibre
      fill: "#4CAF50"
      fill-opacity: 0.4

  source/livelihood-zones:
    uri: data/livelihood_zones.geojson
    type: vector
    description: >
      FEWS NET Livelihood Zones for Malawi (11 zones, 2003 delineation).
      Attributes: food from own farm %, wage labor income %,
      cash crop income %, disaster coping strategy %.
    style:
      renderer: maplibre
      fill: "#FF9800"
      fill-opacity: 0.3
      stroke: "#E65100"
      stroke-width: 1

  source/drought-raster:
    uri: data/drought_exposure.tif
    type: raster
    description: >
      Drought physical exposure index (UNEP/GRID, SPI-based, 1980-2001).
      Continuous values representing drought frequency and severity.
    style:
      renderer: maplibre
      palette: ylorrd
      opacity: 0.7

  source/flood-raster:
    uri: data/flood_risk.tif
    type: raster
    description: >
      Flood physical exposure index (UNEP/GRID, 1999-2007).
      Integer classes representing flood frequency zones.
    style:
      renderer: maplibre
      palette: blues
      opacity: 0.7

  source/lakes:
    uri: data/lakes.geojson
    type: vector
    description: Major water bodies (Lake Malawi, Lake Chilwa, etc.)
    style:
      renderer: maplibre
      fill: "#2196F3"
      fill-opacity: 0.5

  source/parks:
    uri: data/national_parks.geojson
    type: vector
    description: National parks and game reserves (excluded from analysis)
    style:
      renderer: maplibre
      fill: "#4CAF50"
      fill-opacity: 0.3

  # ============================================================
  # ADAPTIVE CAPACITY (40% of vulnerability)
  #
  # DHS household indicators → normalized → weighted sum per TA.
  # Pre-aggregated in prep_data.py; this layer rasterizes the
  # TA-level scores onto the common grid.
  # ============================================================

  capacity/ta-raster:
    type: raster
    description: >
      Adaptive capacity scores rasterized from TA polygons.
      Higher values = greater adaptive capacity (less vulnerable).
      Scale: 0-40 (40% weight in final composite).
    compute:
      op: raster_rasterize
      params:
        attribute: capacity_score
        background: 0.0
        all_touched: true
        dtype: float32
      inputs:
        features: { layer: source/dhs-households }
        reference: { layer: source/drought-raster }
    style:
      renderer: maplibre
      palette: greens
      opacity: 0.7
      info:
        fields: [value]
        format: "Adaptive capacity: {value:.1f}"
        section: Vulnerability Components

  # ============================================================
  # LIVELIHOOD SENSITIVITY (20% of vulnerability)
  #
  # FEWS NET livelihood zone attributes → normalized → weighted sum.
  # Rasterized from zone polygons.
  # ============================================================

  sensitivity/lhz-raster:
    type: raster
    description: >
      Livelihood sensitivity scores rasterized from FEWS NET zones.
      Higher values = greater sensitivity (more vulnerable).
      Scale: 0-20 (20% weight in final composite).
    compute:
      op: raster_rasterize
      params:
        attribute: sensitivity_score
        background: 0.0
        all_touched: true
        dtype: float32
      inputs:
        features: { layer: source/livelihood-zones }
        reference: { layer: source/drought-raster }
    style:
      renderer: maplibre
      palette: oranges
      opacity: 0.7
      info:
        fields: [value]
        format: "Livelihood sensitivity: {value:.1f}"
        section: Vulnerability Components

  # ============================================================
  # PHYSICAL EXPOSURE (40% of vulnerability)
  #
  # Drought + flood rasters reclassified to quintiles, each
  # contributing 20% of the final score (combined 40%).
  # ============================================================

  exposure/drought-classified:
    type: raster
    description: >
      Drought exposure reclassified to quintiles (0-4) then scaled
      to 0-20 range (20% contribution to vulnerability).
    compute:
      op: raster_reclassify
      params:
        method: quantile
        n_classes: 5
        class_values: [0.0, 5.0, 10.0, 15.0, 20.0]
      inputs:
        raster: { layer: source/drought-raster }
    style:
      renderer: maplibre
      palette: ylorrd
      opacity: 0.7
      info:
        fields: [value]
        format: "Drought exposure: {value:.0f}/20"
        section: Vulnerability Components

  exposure/flood-classified:
    type: raster
    description: >
      Flood exposure reclassified to quintiles (0-4) then scaled
      to 0-20 range (20% contribution to vulnerability).
      Note: prep_data.py resamples the flood raster to match the
      drought raster grid (they have different native resolutions).
    compute:
      op: raster_reclassify
      params:
        method: quantile
        n_classes: 5
        class_values: [0.0, 5.0, 10.0, 15.0, 20.0]
      inputs:
        raster: { layer: source/flood-raster }
    style:
      renderer: maplibre
      palette: blues
      opacity: 0.7
      info:
        fields: [value]
        format: "Flood exposure: {value:.0f}/20"
        section: Vulnerability Components

  # ============================================================
  # EXCLUSION MASK
  #
  # Lakes (buffered 500m) + national parks → binary mask.
  # Pixels inside exclusion zones get nodata in the final composite.
  # ============================================================

  exclusion/lake-buffer:
    type: vector
    description: Lake Malawi and other water bodies buffered 500m
    compute:
      op: vector_buffer
      params:
        distance: 500
        units: meters
      inputs:
        geometry: { layer: source/lakes }
    style:
      renderer: maplibre
      fill: "#90CAF9"
      fill-opacity: 0.3

  exclusion/mask-raster:
    type: raster
    description: >
      Binary exclusion mask: 1 = valid analysis area, 0 = excluded
      (lakes + buffer, national parks). Used to mask the final composite.
    compute:
      op: raster_rasterize
      params:
        fill_value: 0.0
        background: 1.0
        all_touched: true
        dtype: float32
      inputs:
        features: { layer: source/parks }
        reference: { layer: source/drought-raster }
    style:
      renderer: maplibre
      palette: greys
      opacity: 0.5

  # ============================================================
  # VULNERABILITY COMPOSITE
  #
  # Map algebra: V = (40 - AdaptiveCapacity) + Sensitivity + Drought + Flood
  # Range: 0 (least vulnerable) to 100 (most vulnerable)
  # ============================================================

  vulnerability/composite:
    type: raster
    description: >
      Final vulnerability index (0-100). Higher = more vulnerable.
      Formula: V = (40 - capacity) + sensitivity + drought + flood.
      Capacity is inverted because higher capacity = less vulnerable.
    compute:
      op: raster_calc
      params:
        expression: "(40.0 - b1) + sensitivity + drought + flood"
      inputs:
        raster: { layer: capacity/ta-raster }
        sensitivity: { layer: sensitivity/lhz-raster }
        drought: { layer: exposure/drought-classified }
        flood: { layer: exposure/flood-classified }
    style:
      renderer: maplibre
      opacity: 0.85
      colorRamp:
        - { value: 0, color: "#1a9850" }
        - { value: 25, color: "#91cf60" }
        - { value: 50, color: "#fee08b" }
        - { value: 75, color: "#fc8d59" }
        - { value: 100, color: "#d73027" }
      info:
        fields: [value]
        format: "Vulnerability: {value:.0f}/100"
        section: Results
      form:
        fields:
          - name: capacity_weight
            type: slider
            min: 0
            max: 1
            step: 0.05
            default: 0.40
            label: Adaptive Capacity Weight
          - name: sensitivity_weight
            type: slider
            min: 0
            max: 1
            step: 0.05
            default: 0.20
            label: Livelihood Sensitivity Weight
          - name: drought_weight
            type: slider
            min: 0
            max: 1
            step: 0.05
            default: 0.20
            label: Drought Exposure Weight
          - name: flood_weight
            type: slider
            min: 0
            max: 1
            step: 0.05
            default: 0.20
            label: Flood Exposure Weight

  vulnerability/classified:
    type: raster
    description: >
      Vulnerability classified into 4 tiers using Jenks natural breaks.
      1 = Low, 2 = Moderate, 3 = High, 4 = Very High.
    compute:
      op: raster_reclassify
      params:
        method: quantile
        n_classes: 4
        class_values: [1.0, 2.0, 3.0, 4.0]
        labels: ["Low", "Moderate", "High", "Very High"]
      inputs:
        raster: { layer: vulnerability/composite }
    style:
      renderer: maplibre
      opacity: 0.8
      colorRamp:
        - { value: 1, color: "#1a9850" }
        - { value: 2, color: "#fee08b" }
        - { value: 3, color: "#fc8d59" }
        - { value: 4, color: "#d73027" }
      info:
        fields: [value]
        format: "Class: {value:.0f}"
        section: Results

  # ============================================================
  # VALIDATION (compare with original paper)
  # ============================================================

  validation/ta-zonal-stats:
    type: table
    description: >
      Mean vulnerability score per Traditional Authority for comparison
      with the original paper's choropleth maps.
    compute:
      op: analysis_zonal_stats
      params:
        stats: [mean, min, max, std]
      inputs:
        raster: { layer: vulnerability/composite }
        zones: { layer: source/ta-boundaries }
    style:
      table:
        renderer: tanstack-table
        columns:
          - { field: zone_id, label: "TA" }
          - { field: mean, label: "Mean Vuln.", format: ".1f" }
          - { field: min, label: "Min", format: ".1f" }
          - { field: max, label: "Max", format: ".1f" }
          - { field: std, label: "Std Dev", format: ".2f" }
        sortBy: mean
        sortOrder: desc
