Table of Contents

Class S104DatasetProcessor

Namespace
EncDotNet.S100.Datasets.Pipelines
Assembly
EncDotNet.S100.Datasets.Pipelines.dll

Pipeline processor for S-104 water-level datasets. Branches between dcf2 (regular grid → coverage layer) and dcf1/dcf8 positioned station series (station-glyph point layer; S-100 Part 10c §10.2.1).

public sealed class S104DatasetProcessor : IDatasetProcessor, ICoveragePortrayalSource, IHeadlessImageRenderer, ITimeAwareDatasetProcessor, ILoadedDatasetProjection, ICoverageSampler
Inheritance
S104DatasetProcessor
Implements
Inherited Members
Extension Methods

Constructors

S104DatasetProcessor(IAssetSource, string, ICrsTransformFactory)

Initializes a new S104DatasetProcessor by reading the HDF5 dataset relativePath from source. Used by exchange-set bulk loading.

public S104DatasetProcessor(IAssetSource source, string relativePath, ICrsTransformFactory crsTransformFactory)

Parameters

source IAssetSource

Asset source holding the dataset (e.g. a folder or ZIP archive).

relativePath string

Path of the dataset file within source.

crsTransformFactory ICrsTransformFactory

Creates the WGS84-to-native CRS transforms used when sampling a gridded dataset for GetCoverageInfo(double, double, DateTime?).

Exceptions

S100DatasetSchemaException

The file does not match the S-104 HDF5 schema. The exception carries the file name.

S100DatasetNotSupportedException

The file uses an S-104 feature this reader does not support. The exception carries the file name.

S104DatasetProcessor(string, ICrsTransformFactory)

Initializes a new S104DatasetProcessor by reading and parsing the HDF5 dataset file at path. The file is read in full and closed before the constructor returns.

public S104DatasetProcessor(string path, ICrsTransformFactory crsTransformFactory)

Parameters

path string

Path to the S-104 HDF5 dataset file.

crsTransformFactory ICrsTransformFactory

Creates the WGS84-to-native CRS transforms used when sampling a gridded dataset for GetCoverageInfo(double, double, DateTime?).

Exceptions

S100DatasetSchemaException

The file does not match the S-104 HDF5 schema. The exception carries the file name.

S100DatasetNotSupportedException

The file uses an S-104 feature this reader does not support. The exception carries the file name.

Fields

IsolineLayerKey

The sub-layer key of the gridded surface's isolines.

public const string IsolineLayerKey = "s104.isolines"

Field Value

string

StationLayerKey

The sub-layer key of the station gauges.

public const string StationLayerKey = "s104.stations"

Field Value

string

Properties

AvailableTimes

Available forecast time steps in this dataset.

public IReadOnlyList<DateTime> AvailableTimes { get; }

Property Value

IReadOnlyList<DateTime>

AxisOrder

The outcome of the dataset-level axis-order check the reader ran on the dataset's positions (issue #650), or null when the product has no positions to check or the reader does not run it. A Swapped outcome means the reader swapped latitude and longitude for the whole dataset (when Normalized is set). Surfaced by hosts (CLI info, the viewer's dataset list) and, when swapped or inconsistent, as a {product}-PROJ-AXIS warning in Validate().

public AxisOrderAssessment? AxisOrder { get; }

Property Value

AxisOrderAssessment

IsGriddedSurface

true when this dataset is a regularly-gridded (dcf2) water-level surface, drawn as isolines, rather than a fixed-station (dcf1 / dcf8) point series. S-104 Edition 2.0.0 defines no official portrayal catalogue and treats water level primarily as input to ECDIS vertical adjustment (see S104CoverageStyle), so the surface is hidden by default in interactive viewers and shown on demand (issue #483). Fixed-station gauges are discrete symbols at genuine tide-station locations and remain visible by default.

public bool IsGriddedSurface { get; }

Property Value

bool

IssueTime

When the producer issued the dataset (UTC), from its issueDate and issueTime (see S100IssueTime); null when the dataset does not say. For a forecast this is usually some time after the model run it carries.

public DateTime? IssueTime { get; }

Property Value

DateTime?

Metadata

The lightweight, product-agnostic DatasetMetadata for this dataset — its declared specification and, where cheaply derivable, its geographic extent, horizontal CRS, display-scale window, and temporal coverage. Overriding processors derive it once from the already-parsed dataset (never a second parse) and cache it, so hosts can frame a viewport, register a layer, draw an out-of-scale indicator, or gate visibility without re-reading the dataset. The default implementation does not override this and instead returns a fresh, minimal value carrying only Spec on each access; processors that can supply an extent (and other facts) override it with the derive-once-and-cache behaviour above. See issue #467 / #460.

public DatasetMetadata Metadata { get; }

Property Value

DatasetMetadata

Remarks

Derived from the already-parsed dataset: for gridded (dcf2) surfaces from the coverage source's georeferencing metadata; for fixed-station (dcf8) series from the union of station coordinates. No HDF5 payload is re-read (issue #467, WS1).

Spec

The product specification (name + edition) this dataset declares conformance to. Each per-spec processor returns a fixed name (e.g. "S-101"); the edition portion is populated from the dataset itself (HDF5 productSpecification attribute, GML application namespace, S-101 ProductSpecificationEdition, etc.) when known, otherwise defaults to SpecVersion default.

public SpecRef Spec { get; }

Property Value

SpecRef

TimeSemantics

What the time steps are, which one is drawn between steps, and how long a step stays valid. Defaults to Default: forecast steps, nearest within the typical step.

public TimeSemantics TimeSemantics { get; }

Property Value

TimeSemantics

Remarks

VersionAssessment

How the dataset's declared product specification edition (Spec) relates to the version of the catalogue used to process it, or null when no catalogue self-describes its version (so no assessment can be made). Computed once at construction — catalogue resolution is a one-shot per processor — and surfaced by hosts (CLI info/render, viewer layer list) to warn on a version mismatch per S-100 Edition 5.2.1 Part 2 §6.

public SpecVersionAssessment? VersionAssessment { get; }

Property Value

SpecVersionAssessment

VerticalDatum

The vertical datum the water levels are heights above: the dataset's verticalDatum as an S-100 vertical datum code (S-104 Ed 2.0.0 §5.2), or null when it isn't declared.

public int? VerticalDatum { get; }

Property Value

int?

WaterLevelTimeSemantics

S-104 water level steps: forecasts, each held until the next step for one typical step. Treated as forecasts until the reader exposes dataDynamicity; an observation would hold its last value for 30 minutes.

public static TimeSemantics WaterLevelTimeSemantics { get; }

Property Value

TimeSemantics

Methods

BuildCoveragePortrayalAsync(RenderContext?, CancellationToken)

Builds an immutable, Mapsui-free snapshot of this dataset's coverage portrayal for the supplied render context. Implementations run under a render gate and materialise the styled coverage (including the selected time step) so the result is safe to convert to Mapsui layers off the gate.

public Task<CoveragePortrayalResult> BuildCoveragePortrayalAsync(RenderContext? context = null, CancellationToken cancellationToken = default)

Parameters

context RenderContext

Optional render context (palette, mariner, time step).

cancellationToken CancellationToken

Cancellation token.

Returns

Task<CoveragePortrayalResult>

The Mapsui-free coverage portrayal result.

CreateLoadedData()

Allocates the LoadedDatasetData variant wrapping this processor's already-parsed model. Never re-reads the source bytes.

public LoadedDatasetData CreateLoadedData()

Returns

LoadedDatasetData

The catalog payload wrapping the resident model (e.g. an S125DatasetData or S102CoverageData).

FindSites(CoverageSampleQuery)

Finds the places in this dataset that can answer a sample at the query's point: the grid node nearest to it, or every station of a station-series dataset (the nearest across datasets is chosen later).

public CoverageSiteSearch FindSites(CoverageSampleQuery query)

Parameters

query CoverageSampleQuery

The point to sample, with the transforms that reproject it into the dataset's CRS.

Returns

CoverageSiteSearch

The sites, or an empty search when the dataset does not cover the point. Implementations may throw ObjectDisposedException when the dataset was closed during the call.

Remarks

Water level height and trend: at the grid node nearest the point for a regular grid (dcf2), or at every station of a station series (dcf8), at the step nearest the requested time.

GetCoverageInfo(double, double, DateTime?)

Samples water level at the supplied geographic position and time. For a gridded (dcf2) dataset the containing grid cell is sampled at time (the nearest available step; the first step when null). For a station series the nearest station is reported at the sample closest to time (its first sample when null).

public FeatureInfo? GetCoverageInfo(double latitude, double longitude, DateTime? time)

Parameters

latitude double

WGS84 latitude in degrees.

longitude double

WGS84 longitude in degrees.

time DateTime?

Time to sample at, or null for the first available time.

Returns

FeatureInfo

Water-level height, trend and sample time, or null when the point lies outside the grid, or the dataset has no time steps or stations.

GetFeatureInfo(string)

Resolves dcf8 station picks routed via the renderer's feature-ref tag the glyph layer attaches to each station point. Refs are formatted as "station:<id>" (see EncDotNet.S100.Datasets.Pipelines.S104DatasetProcessor.StationFeatureRefPrefix). For dcf2 gridded datasets and other refs this returns null; callers should fall back to GetCoverageInfo(double, double, DateTime?).

public FeatureInfo? GetFeatureInfo(string featureRef)

Parameters

featureRef string

Returns

FeatureInfo

RenderHeadlessAsync(int, int, RenderContext?, RgbaColor?, CancellationToken)

Renders the water-level portrayal to a standalone SKBitmap through the headless, Mapsui-free Skia path. The selected time step is taken from TimeStep, defaulting to the first available step.

public Task<SKBitmap> RenderHeadlessAsync(int widthPixels, int heightPixels, RenderContext? context = null, RgbaColor? background = null, CancellationToken cancellationToken = default)

Parameters

widthPixels int

Output bitmap width in pixels.

heightPixels int

Output bitmap height in pixels.

context RenderContext

Optional render context (palette, time step, mariner settings).

background RgbaColor?

Optional background fill; defaults to opaque white.

cancellationToken CancellationToken

Cancellation token.

Returns

Task<SKBitmap>

A newly allocated bitmap owned by the caller.

Validate()

Runs the S-104 normative rule pack (Default) against the parsed dataset and returns the cached report. Returns null when the loaded HDF5 has no validatable shape (defensive — currently unreachable because the constructor produces either a S104DatasetData.GriddedCoverage or a S104DatasetData.StationSeries, both of which this method handles).

public ValidationReport? Validate()

Returns

ValidationReport

Remarks

Per docs/design/non-gml-validation.md §5.1 and §5.3, this override surfaces reader-time projection diagnostics under reserved rule ids:

  • S104-PROJ-SCHEMA — defensive try/catch for S100DatasetSchemaException. The realistic failure mode is the constructor itself throwing, so this only fires if a future reader change moves schema validation later in the pipeline.
  • Station-series datasets are checked directly for sample shape, explicit timestamp ordering, and valid trend codes because the gridded V-2 rule pack operates on S104Dataset.

Validation is a pure function of the parsed dataset; the report is cached after the first call (mirroring the V-1 S-102 processor and the GML processors' pattern).