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:
- Filter candidate snap features by search radius.
- Prefer the highest
weight. - Break ties by
stem_role = "mainstem"when available. - Break remaining ties by distance to the outlet point.
- 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
snapartifact key is present. metadata.nameis present, kebab-case, and unique across snap declarations.metadata.description,metadata.references_levels, andmetadata.weight_semanticsare present.metadata.references_levelsis 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.
idvalues are positive and unique.unit_idvalues reference existing units incatchments.parquet.- Referenced unit levels are listed in
metadata.references_levels. weightvalues are finite and non-negative.stem_role, when present, ismainstem,tributary,distributary, orunknown.- When the
bboxstruct 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 atgeo.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.