Skip to content

Auxiliary schema

This page renders spec/aux/snap/v2.md from main.

HFX Auxiliary Schema: Snap v2

Schema ID: hfx.aux.snap.v2

Normative keywords in this document are to be interpreted as described in RFC 2119.

hfx.aux.snap.v2 declares optional reach or node geometries used to attach an outlet point to a drainage unit. Snap features are not a replacement for unit outlets. Multiple declarations MAY appear in one manifest when different snap feature sets reference different HFX levels.

hfx.aux.snap.v2 supersedes hfx.aux.snap.v1. The breaking change is the bounding box: v1's four flat float32 columns (bbox_minx, bbox_miny, bbox_maxx, bbox_maxy) are replaced by a single nullable bbox struct whose non-nullable leaves are xmin, ymin, xmax, and ymax, declared as a GeoParquet 1.1 covering. Per the auxiliary versioning rule a breaking change increments the auxiliary vN, so this is v2.

Manifest Declaration

{
  "schema": "hfx.aux.snap.v2",
  "artifacts": {
    "snap": "snap/segment_stems.parquet"
  },
  "metadata": {
    "name": "segment-stems",
    "description": "Segment-scale stems for coarse unit snapping.",
    "references_levels": [0],
    "weight_semantics": "Higher values indicate stronger drainage dominance."
  }
}

Multi-Entry Example

{
  "auxiliary": [
    {
      "schema": "hfx.aux.snap.v2",
      "artifacts": {
        "snap": "snap/segment_stems.parquet"
      },
      "metadata": {
        "name": "segment-stems",
        "description": "Segment-scale stems for level 0 units.",
        "references_levels": [0],
        "weight_semantics": "Higher values indicate stronger drainage dominance."
      }
    },
    {
      "schema": "hfx.aux.snap.v2",
      "artifacts": {
        "snap": "snap/reach_stems.parquet"
      },
      "metadata": {
        "name": "reach-stems",
        "description": "Reach-scale stems for level 1 units.",
        "references_levels": [1],
        "weight_semantics": "Higher values indicate stronger drainage dominance."
      }
    }
  ]
}

Required Artifact Keys

Key Description
snap Snap-feature Parquet file

The artifact path is relative to the HFX dataset root and MUST NOT escape it.

Required Metadata

Field Type Required Description
name string Yes Kebab-case name unique across all snap declarations in the dataset
description string Yes Human-readable description of this snap feature set
references_levels int[] Yes Non-empty list of HFX levels this snap file MAY reference
weight_semantics string Yes Producer documentation for how weight values are interpreted

Additional metadata fields are allowed only after this schema version is extended additively.

Parquet Schema

Allowed geometry types are Point and LineString.

Column Type Nullable Description
id int64 No Unique snap feature ID within this dataset
unit_id int64 No Referenced drainage unit ID
weight float32 No Producer-defined preference for snapping
stem_role string Yes One of mainstem, tributary, distributary, or unknown when known
bbox struct<xmin: float32, ymin: float32, xmax: float32, ymax: float32> Yes Optional GeoParquet 1.1 covering bounding box; the struct is nullable, but when a row's bbox is non-null all four leaves MUST be non-null
geometry binary WKB No Point or LineString, EPSG:4326

The bbox column is OPTIONAL: a producer MAY omit it entirely. When present, it is a Parquet struct with four non-nullable float32 leaves (xmin, ymin, xmax, ymax). The struct itself is nullable so a producer MAY leave individual rows without bounds; a non-null bbox MUST carry all four leaves.

Snap files do not store a level column. The level is derived from the referenced unit and MUST be listed in metadata.references_levels.

Bounding Box Covering

When the bbox struct column is present, it MUST be declared as a GeoParquet 1.1 covering in the file-level geo metadata, using the same convention as catchments.parquet. With geometry as the primary geometry column, the covering MUST be declared at the literal path geo.columns.geometry.covering.bbox.{xmin,ymin,xmax,ymax}, where each entry is the column-path reference to the matching struct leaf:

{
  "version": "1.1.0",
  "primary_column": "geometry",
  "columns": {
    "geometry": {
      "encoding": "WKB",
      "geometry_types": ["Point", "LineString"],
      "covering": {
        "bbox": {
          "xmin": ["bbox", "xmin"],
          "ymin": ["bbox", "ymin"],
          "xmax": ["bbox", "xmax"],
          "ymax": ["bbox", "ymax"]
        }
      }
    }
  }
}

All four covering references MUST point at leaves of the same struct column named bbox, per the GeoParquet 1.1 requirement that the four covering bbox references share one column. When the bbox column is present, Parquet row-group statistics on its leaves bbox.xmin, bbox.ymin, bbox.xmax, and bbox.ymax MUST be written; those statistics are what drive predicate pushdown.

Snapping Semantics

The engine MAY use any runtime snap strategy, but the default HFX interpretation is a weight-first cascade:

  1. Filter candidate snap features by search radius.
  2. Prefer the highest weight.
  3. Break ties by stem_role = "mainstem" when available.
  4. Break remaining ties by distance to the outlet point.
  5. Break final ties by ascending snap id.

Snap features do not encode internal snap-to-snap connectivity. Reach routing, hydraulic models, and stream-order computations belong in auxiliary data or engine-specific inputs.

weight values MUST be finite and non-negative. The phrase "monotonically increasing in drainage dominance" describes the semantic intent of the column, not a structural constraint enforced by validators.

Validation Expectations

A validator implementing this schema checks:

  • The snap artifact key is present.
  • metadata.name is present, kebab-case, and unique across snap declarations.
  • metadata.description, metadata.references_levels, and metadata.weight_semantics are present.
  • metadata.references_levels is non-empty and contains non-negative integers.
  • The artifact path resolves inside the dataset root.
  • The file is present and readable as Parquet.
  • Required columns exist with the specified physical types and nullability.
  • id values are positive and unique.
  • unit_id values reference existing units in catchments.parquet.
  • Referenced unit levels are listed in metadata.references_levels.
  • weight values are finite and non-negative.
  • stem_role, when present, is mainstem, tributary, distributary, or unknown.
  • When the bbox struct column is present, its four non-nullable leaves (bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax) are finite and ordered for every non-null row, the covering is declared at geo.columns.geometry.covering.bbox.{xmin,ymin,xmax,ymax}, and row-group statistics are present on each leaf.
  • Geometries are structurally valid WKB Point or LineString values in EPSG:4326.