Layer format¶
The layer format is the only interface between openwater (which writes layers and projects) and the viewer and docs (which read them). It is defined in openwater/src/openwater/spec/: the JSON Schemas layer.schema.json and project.schema.json plus the feature rules in spec/__init__.py. The viewer image contains a copy of the schemas and nothing else from openwater.
Current version: 1 (spec_version in every layer.json).
A layer package¶
<data dir>/layers/<layer id>/
├── layer.json metadata (below), validated against layer.schema.json
└── data.geojson FeatureCollection with the features
Consumers may add their own files to the folder (the viewer adds style.json, tiles.pmtiles, .tiles.json). openwater never touches them, and replaces layer.json and data.geojson atomically on every export.
Layer ids are lowercase letters, digits and hyphens, e.g. kiel-hydrants.
data.geojson¶
- One
FeatureCollection. Geometry type matcheslayer.json → geometry:Point;LineString/MultiLineString;Polygon/MultiPolygon. Coordinates in WGS84. - Each feature's
propertiesare exactly the layer's attributes, with the declared type, present unless the attribute isoptional, and forclosedattributes one of the listed values. - If
osm_tagsis true, features also carry their raw OSM tags asosm:<key>. - No other properties.
layer.json¶
| Field | Content |
|---|---|
spec_version |
"1" |
id, title, description |
Identity and texts |
geometry |
point, line or polygon |
region |
{id, name} |
bbox |
[west, south, east, north] |
data |
{file: "data.geojson", count, sha256}. The checksum lets consumers detect changed data |
generated_at, osm_timestamp |
When exported; state of the OSM data |
generator |
{name, version, script} |
parameters |
Name → {value, unit, description} |
osm_tags |
Whether features carry osm:<key> tags |
attributes |
Attribute id → {type, label, description, unit, optional, closed, values, source} in evaluation order. values: value key → {label, description}, booleans as "true"/"false". source documents how the value was produced (osm_id, feature_id, tag, matching_rules, none_matched, nearest, classify, sum_within, index, value_at, with their parameters) |
rule_sets |
Id → {title, description, attribute, rules}; attribute holds the ids of matching rules; each rule {id, title, description, where, source, status} |
assumptions |
[{id, title, description, status}] |
planned |
[{id, title, description, step}] |
sources |
[{id, title, used_for, url, license, license_url, attribution}] |
stats |
{count, value_counts, completeness, rule_counts, numeric}: features per value (attributes with values and booleans), share of features where an attribute's OSM tag is present, features per rule, and for numeric attributes min, max, mean, p25–p95 (optional; the viewer scales heat maps with it) |
Status of rules and assumptions: assumption (working hypothesis, not yet checked), verified (confirmed by a named source), rejected (kept for the record, no longer applied).
Conditions (where in rules, in nearest and in classify cases): attribute id → a scalar (equals), a list (one of), {"op": "not_empty"}, {"op": "empty"}, {"op": "min", "value": x}, {"op": "max", "value": x}. All must hold; a condition on an absent attribute is false except empty.
Projects¶
A project groups layers that are shown together, e.g. the five layers of one study region. The viewer shows one project at a time; the docs list the layers by project.
<data dir>/projects/<project id>.json
| Field | Content |
|---|---|
spec_version |
"1" |
id, title, description |
Identity and texts; the id matches the file name |
layers |
[{id, visible}] in drawing order, the first on top. visible: false = listed but switched off when the project is opened |
generated_at, generator |
When exported; {name, version, script} |
The layers are referenced by id and live in layers/<id>/; a layer may belong to several projects, and a layer in no project is not shown on the map. A project may list a layer that isn't exported yet; the viewer shows it as missing.
Checking a package¶
from openwater import spec
spec.package_errors("data/viewer/layers/kiel-hydrants") # [] if valid
spec.project_errors(doc) checks a project document. The viewer checks layer.json and project files against the schemas and lists invalid ones in Settings with the reason, without loading them.
Changing the format¶
The format is versioned. Additions that old readers can ignore keep the version (e.g. a new optional field). Anything that changes the meaning of existing fields needs a new spec_version, an update of the viewer and docs, and a re-export of all layers.