name: storm-events-aoi
version: "0.1"
status: draft
category: events-hazards
themes: [hazards, weather]
family: storm-impact-aoi-summary
description: >
  Storm damage totals by event type within an area of interest, 1950-present.
  Reads NOAA's Storm Events Database (~2.0M events) as cloud-native GeoParquet,
  clips to the AOI by bounding-box overlap, and aggregates event counts,
  property + crop damage, deaths, and injuries grouped by event type. Answers
  "what has hit this place, how often, and how bad?" for any US location. The
  filtered event rows are the show-your-work — every dollar in the total traces
  back to a specific NCEI event record.

# Example AOI: East Texas / Houston band (hurricanes, flooding, tornadoes).
settings:
  aoi_west: -98.7
  aoi_south: 29.2
  aoi_east: -94.8
  aoi_north: 33.0

inputs:
  aoi:
    bbox: [-98.7, 29.2, -94.8, 33.0]
    notes: >
      Bounding-box AOI. Events carry a `bbox` STRUCT column (xmin/ymin/xmax/ymax),
      so overlap filtering needs no spatial extension — plain DuckDB comparisons.
  dataset:
    uri: "@noaa/storm-events"

layers:

  # ── SOURCE ──────────────────────────────────────────────────────────────
  source/events:
    type: vector
    uri: "@noaa/storm-events"
    description: NOAA Storm Events GeoParquet — one row per event, with damage columns and a bbox struct.
    params:
      asset: events.parquet

  # ── COMPUTE ─────────────────────────────────────────────────────────────
  compute/in-aoi:
    type: table
    description: Events whose bounding box overlaps the AOI rectangle.
    compute:
      op: tabular_filter
      inputs:
        table: { layer: source/events }
      params:
        where: >
          bbox.xmin <= ${settings.aoi_east} AND bbox.xmax >= ${settings.aoi_west}
          AND bbox.ymin <= ${settings.aoi_north} AND bbox.ymax >= ${settings.aoi_south}

  # ── RESULT ──────────────────────────────────────────────────────────────
  result/by-event-type:
    type: table
    description: One row per event type — count, total property + crop damage (USD), casualties.
    compute:
      op: tabular_aggregate
      inputs:
        table: { layer: compute/in-aoi }
      params:
        group_by: [event_type]
        aggregations:
          events: "COUNT(*)"
          damage_property_usd: "SUM(damage_property)"
          damage_crops_usd: "SUM(damage_crops)"
          deaths: "SUM(deaths_direct + deaths_indirect)"
          injuries: "SUM(injuries_direct + injuries_indirect)"
        order_by: ["damage_property_usd DESC"]

outputs:
  primary:
    - result/by-event-type       # Parquet — damage leaderboard by event type
  show_your_work:
    - compute/in-aoi             # the exact event rows behind every total

license:
  recipe: Apache-2.0
  output_dataset: public-domain
  upstream_data:
    - { source: "@noaa/storm-events", license: public-domain }
