Table of Contents

Class S111SurfaceCurrentRules

Namespace
EncDotNet.S100.Datasets.S111.Validation
Assembly
EncDotNet.S100.Datasets.S111.dll

The default ValidationRuleSet<TModel> of normative rules for an S-111 S111Dataset. Rule identifiers follow the convention S111-R-{clause} for normative rules and S111-PROJ-{kind} for projection-diagnostic surrogates, traceable back to S-111 (Edition 2.0.0) and S-100 Part 10c.

public static class S111SurfaceCurrentRules
Inheritance
S111SurfaceCurrentRules
Inherited Members

Remarks

This is the V-3 rule pack as defined in docs/design/non-gml-validation.md §6.3. Rules read off the strongly-typed S111Dataset produced by S111DatasetReader; structural-schema failures the reader cannot tolerate are thrown as S100DatasetSchemaException at read time (and unsupported data-coding-format selections — e.g. dcf 3 ungeorectified grid or dcf 8 time series at fixed stations, which are projected onto S111StationSeriesDataset instead of S111Dataset — as S100DatasetNotSupportedException) and (per design §5.1 and §5.3) surfaced as S111-PROJ-SCHEMA / S111-PROJ-UNSUPPORTED findings by the dataset processor's Validate() wrapper.

V-3 mirrors V-2 (S-104) almost exactly: the time-axis rule pattern from V-2's S104-R-2.1 / S104-R-2.2 is folded into a single S111-R-2.1 (monotonicity-then-cadence) per design §6.3.

Tier-3 cross-dataset rules are out of scope; per-finding payload conventions follow design §4.3:

  • per-coverage finding — RelatedFeatureId = "{groupPath}"
  • per-time-step finding — RelatedFeatureId = "{groupPath}#timePoint"

Properties

CoverageValuesLengthMatchesShape

S111-R-1.1 — Every SurfaceCurrentCoverage's Values array length equals NumPointsLatitudinal × NumPointsLongitudinal.

public static IValidationRule<S111Dataset> CoverageValuesLengthMatchesShape { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

Spec reference: S-100 Part 10c §10.2.1.2 (gridded coverage shape contract) and S-111 Edition 2.0.0 §12 (SurfaceCurrent feature). Implements the s111-surface-currents skill review-checklist item "HDF5 layout under /SurfaceCurrent/SurfaceCurrent.NN/Group_NNN/values matches spec".

Default

The canonical default rule set for S-111 surface-current datasets.

public static ValidationRuleSet<S111Dataset> Default { get; }

Property Value

ValidationRuleSet<S111Dataset>

ProjectionSchemaSurrogate

S111-PROJ-SCHEMA — defensive projection-diagnostic surrogate (design §5.1, §5.3).

public static IValidationRule<S111Dataset> ProjectionSchemaSurrogate { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

The rule body is intentionally a no-op: by the time the rule pack runs the dataset is already constructed, so any S100DatasetSchemaException has already thrown out of the reader. The rule id is reserved in this rule set so that S111DatasetProcessor.Validate() can emit a single-finding report carrying the exception's GroupPath, AttributeOrDataset, and SpecReference under this same rule id when the defensive try/catch around the rule-pack call fires.

ProjectionUnsupportedSurrogate

S111-PROJ-UNSUPPORTED — projection-diagnostic surrogate for an S100DatasetNotSupportedException (design §5.3). In practice this fires when the underlying HDF5 dataset uses a data coding format the gridded S111Dataset view does not cover — currently dcf 3 (ungeorectified grid) and dcf 8 (time series at fixed stations), both of which the reader projects onto S111StationSeriesDataset instead — or when a future reader change rejects an additional format.

public static IValidationRule<S111Dataset> ProjectionUnsupportedSurrogate { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

The rule body is a no-op (analogous to ProjectionSchemaSurrogate); S111DatasetProcessor.Validate() emits findings under this rule id directly when it observes the station-series variant or when its defensive try/catch traps the exception.

SurfaceCurrentDepthInRange

S111-R-3.1 — SurfaceCurrentDepth, when present, has a plausible magnitude: within 1500 metres of its reference level, either side. Skipped entirely when the attribute is absent / null (it is optional on the dataset root).

public static IValidationRule<S111Dataset> SurfaceCurrentDepthInRange { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

Spec reference: S-111 Edition 1.x / 2.0.0 root attribute surfaceCurrentDepth, interpreted per depthTypeIndex. For a height or depth relative to a datum (sea surface, sea bottom, or a tidal datum) the vertical axis is directed upward, so a current level below the reference surface is negative (NOAA's OFS products write -4.5 m below the sea surface); for a layer average the value is the positive layer thickness. The sign therefore depends on the reference and is not checked — only the magnitude is.

The 1500 m bound is a plausibility heuristic (currents reported as "surface" are typically tens of metres deep at most; magnitudes beyond 1500 m almost certainly indicate a unit error). Implements the "root-attribute completeness" conditional pattern in design §7.5.

SurfaceCurrentDirectionsInRange

S111-R-4.2 — Non-NODATA surface current directions across each coverage lie within the half-open range [0, 360) degrees true. Note the upper bound is exclusive: 360.0 is invalid (per spec convention it must wrap to 0). NODATA cells (EncDotNet.S100.Datasets.S111.Validation.S111SurfaceCurrentRules.NoDataValue, NaN, ±infinity) are skipped.

public static IValidationRule<S111Dataset> SurfaceCurrentDirectionsInRange { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

Spec reference: S-111 Edition 2.0.0 §12; surfaceCurrentDirection compound member, degrees true, "going to" oceanographic convention (also documented on Direction). Implements the s111-surface-currents skill review-checklist item "surfaceCurrentDirection (float32, degrees true, 0–360)" and the known pitfall "Wrap-around at 360° must be handled".

SurfaceCurrentSpeedsInPlausibleRange

S111-R-4.1 — Non-NODATA surface current speeds across each coverage lie within the plausible range [0, 15] metres per second. NODATA cells (finite values equal to EncDotNet.S100.Datasets.S111.Validation.S111SurfaceCurrentRules.NoDataValue, plus NaN and ±PositiveInfinity) are excluded from the range check.

public static IValidationRule<S111Dataset> SurfaceCurrentSpeedsInPlausibleRange { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

S-111 stores Speed in knots (S-111 Edition 2.0.0 §12; compound member surfaceCurrentSpeed). The plausibility bound in design §6.3 is expressed in m/s; this rule converts each value via EncDotNet.S100.Datasets.S111.Validation.S111SurfaceCurrentRules.KnotsToMetresPerSecond before comparing. 15 m/s (~29.2 knots) comfortably accommodates strong tidal currents and the fastest western-boundary currents while catching the common producer mistake of reporting cm/s where m/s was assumed (a 100x scale error) or vice versa.

One finding per offending coverage with the count of out-of-range cells in the message; emitting one finding per cell on a broken tile would drown the report in cascade noise (design §6.3 / §7.2).

Implements the s111-surface-currents skill known pitfall "Speed units vary by producer".

TimePointMonotonicityAndCadence

S111-R-2.1 — Coverages ordered by TimePoint are strictly increasing and their successive deltas vary by no more than ±10% of the median delta. Per design §6.3 the S-111 time-axis check folds the V-2 monotonicity (S104-R-2.1) and cadence (S104-R-2.2) into a single rule.

public static IValidationRule<S111Dataset> TimePointMonotonicityAndCadence { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

Walks the time-point sequence in two passes:

  1. Monotonicity — emits a single finding at the first non-strictly-increasing step and returns immediately; later violations are usually cascade noise (design §7.2).
  2. Cadence — only entered when the sequence is monotonic. Skipped when Coverages.Count < 3 (a single delta has no comparison). The median (not the mean) delta is the reference so a single missing step does not skew the tolerance for the rest of the series.

Spec reference: S-111 Edition 2.0.0 §12 (per-Group_NNN timePoint attribute) and §10 (timeRecordInterval); S-100 Part 10c §10.2.6 (time-series group sequence). Implements the s111-surface-currents skill review-checklist item "times derived from dateTimeOfFirstRecord + timeRecordInterval".

TypeOfCurrentDataInEnumeratedSet

S111-R-3.2 — TypeOfCurrentData, when present, is a member of the S-111 enumerated set (see EncDotNet.S100.Datasets.S111.Validation.S111SurfaceCurrentRules.ValidTypeOfCurrentData). Skipped entirely when the attribute is absent / null.

public static IValidationRule<S111Dataset> TypeOfCurrentDataInEnumeratedSet { get; }

Property Value

IValidationRule<S111Dataset>

Remarks

Spec reference: S-111 Edition 2.0.0 §10 / §12 (root attribute typeOfCurrentData on the /SurfaceCurrent container); enumeration values published in the S-100 GI Registry. Implements the s111-surface-currents skill review-checklist item "root attributes include typeOfCurrentData".

Methods

Validate(S111Dataset, ValidationContext?)

Convenience wrapper around Run(TModel, ValidationContext?) using the Default rule set.

public static ValidationReport Validate(S111Dataset dataset, ValidationContext? context = null)

Parameters

dataset S111Dataset
context ValidationContext

Returns

ValidationReport