On this page
An ocean-data web application can return the correct number and still communicate the wrong meaning. The unit may be missing, a fill value may have become zero, an adjusted measurement may be paired with the raw variable’s quality flag, or an interpolated point may look indistinguishable from an observation.
These failures are data-contract failures. They occur when scientific meaning is left implicit at a boundary between NetCDF, preprocessing, storage, an API, and the browser.
This article defines a practical contract for carrying ocean observations through those boundaries. It builds on From NetCDF to the Browser: Designing a Web App for Ocean Data and focuses on the fields that must survive the trip.
A Number Is Not a Scientific Payload
The fragile version of an API sends 34.72 and relies on the front end, a filename, or team memory to explain it. The defensible version sends enough context for the client to label, validate, and trace the value.
The exact schema varies by product, but the contract should make invalid combinations difficult to create. A browser should not have to guess whether 0 means a real measurement, missing data, or a failed conversion.
Units: Name the Quantity Before Formatting It
Units belong to the variable definition, not just the axis label. Preserve the source quantity and record every conversion.
For each variable, define:
- a stable machine name;
- a human-readable label;
- the stored unit;
- the unit or units offered for display;
- the conversion method and version if conversion is not trivial;
- the valid physical or operational range used for validation, if any.
Avoid using an ambiguous key such as temperature when the system can contain in-situ temperature, potential temperature, and conservative temperature. Avoid calling every salinity value PSU: practical salinity is dimensionless, while absolute salinity is commonly expressed in grams per kilogram. The UI can use accessible wording, but the data layer should remain precise.
Keep conversion out of ad hoc chart callbacks. A single, tested transformation should produce both the displayed values and the displayed unit. If users can switch units, retain the canonical stored value so repeated conversions do not accumulate rounding error.
Missing Values: Preserve Absence as Absence
NetCDF variables can use fill values or missing-value attributes. These sentinels must be decoded before arithmetic, statistics, interpolation, or JSON serialization.
The safe sequence is:
- Read the variable and its declared missing representation.
- Convert fill values to the language’s missing/nullable representation.
- Apply aligned QC and selection rules.
- Calculate derivatives only from valid inputs.
- Serialize missing values as
nullor omit them according to a documented schema.
Do not replace missing values with zero merely because JSON does not support NaN. Zero degrees, zero oxygen, zero depth, and zero velocity can all be real values. Substitution changes a statement of “not available” into a measurement.
For an aligned profile payload, keep the pressure coordinate numeric and let every parameter cell be number | null. Deleting the entire pressure row because one parameter is missing also deletes valid measurements from unrelated sensors. Keeping the row and its null cells makes pairwise analysis explicit and lets the browser draw only the finite points.
Missingness also has structure. Distinguish when useful between:
- the instrument did not observe this parameter;
- the source contained a fill value;
- quality filtering rejected the value;
- a derived calculation lacked a required input;
- interpolation deliberately left a gap;
- the payload omitted a field to reduce transfer size.
Not every interface needs to display all six states, but the pipeline should not erase distinctions needed for debugging or scientific explanation.
QC: Keep the Decision with the Selected Value
Argo profile files include parameter-specific QC arrays and both raw and adjusted fields. The official Argo profile-file guide describes PARAM_QC, PARAM_ADJUSTED, and data modes.
If preprocessing selects an adjusted value, it must evaluate the matching adjusted QC field. If it falls back to a raw value, it must evaluate the raw QC field. Related coordinates and variables must stay aligned through filtering.
A web payload does not always need every original flag, but it should record at least:
- the selected representation, such as raw or adjusted;
- the accepted-flag policy or its version;
- whether the value survived that policy;
- a link or identifier for the detailed filtering documentation.
This is preferable to a vague boolean named quality: true. A boolean does not tell a future developer which rule created it.
Argo Data Quality Control Guide: QC Flags and Adjusted vs. Raw Data gives a fuller explanation of adjusted values, data modes, and flag selection. OceanGraph’s current user-facing rules are documented in its Data Filtering Policy.
Identity and Coordinates: Make Every Point Traceable
A point in a chart should be traceable to an observation. For a profile dataset, useful identity fields can include:
- platform or WMO identifier;
- cycle, cast, station, or deployment identifier;
- observation time with time zone convention;
- latitude and longitude with coordinate reference convention;
- source file or archive key;
- parameter and vertical-level index.
Use stable identifiers in URLs and API responses where practical. Array positions such as “profile 17” are not stable after filtering or a new data release.
Time needs particular care. Serialize an unambiguous instant, commonly ISO 8601 in UTC, and localize only for display. A date without time zone information should not silently pass through a system that combines cruises or sensors from different regions.
Longitude conventions also need one deliberate rule. A mix of 0–360 and −180–180 can place valid observations on the wrong side of a map or break a dateline-crossing query.
Provenance: Record Enough to Rebuild the Answer
Provenance is not a paragraph added after deployment. It is data produced by the pipeline.
At minimum, record:
- source dataset and snapshot or retrieval time;
- source identifiers or file paths;
- processing code revision;
- configuration and QC-policy version;
- relevant dependency or algorithm version for derived variables;
- output dataset version and generation time.
For a value derived from multiple inputs, keep a route back to those inputs at a practical granularity. That may be a profile-level source record rather than a full lineage graph for every pixel. The goal is a proportionate answer to: “Which data and rules produced what I see?”
Argo provides acknowledgement and citation guidance. A product-level provenance page can supply the dataset DOI and processing description, while the selected profile supplies its specific identity.
An Example API Contract
The following example is deliberately small. It shows one selected temperature value after preprocessing:
{
"profile_id": "5904935/0280",
"observed_at": "2022-10-06T11:50:07Z",
"position": { "latitude": 23.935, "longitude": 143.876 },
"vertical": { "value": 1000.0, "unit": "dbar" },
"parameter": "potential_temperature",
"measurement": { "value": 4.18, "unit": "degC" },
"selection": {
"representation": "processed",
"qc_policy": "ocean-profile-policy-v1"
},
"provenance": {
"source_dataset": "Argo",
"source_profile": "5904935 cycle 280",
"output_version": "2026-07-31"
}
}
API schema documentation must define nullability, allowed parameter names, precision, and whether the vertical coordinate is observed or derived.
Avoid copying large provenance blocks beside every point. A profile payload can declare common context once and carry aligned arrays below it. Normalize for meaning; denormalize deliberately for delivery efficiency.
Interpolation Must Not Erase Observation Gaps
This salinity section comes from the same read-only OceanGraph Argo processing snapshot used in the architecture article. It demonstrates an important contract: the plotted surface includes both values and an availability mask. The white areas are not zero salinity and should not be colored as if they were observations.
Interpolation creates an estimate between observations. If a product uses it, record:
- the coordinate on which interpolation occurs;
- the method;
- maximum supported gap, extrapolation rule, and boundary behavior;
- which values are observed, interpolated, or unavailable;
- the version of the rule.
The public profile and a derived visualization need not use the same representation. OceanGraph keeps null in the profile data it serves, then lets a chart or an analysis interpolate between observations when a regular grid is required, never beyond them. That separation prevents a convenient plotting estimate from being mistaken for an original profile value.
The interface can present a clean surface while still exposing gaps and method notes. Time-Series Vertical Sections in Oceanography Explained (With Argo Examples) discusses why time and depth sampling matter when reading such a view.
Separate Scientific Values from Presentation State
The browser often needs additional state: color range, selected unit, rounded tooltip text, current depth window, and whether a layer is hidden. Do not write those presentation choices back into the scientific payload.
A useful separation is:
- Scientific state: canonical value, unit, coordinates, missing state, QC decision, provenance.
- View state: selected palette, scale limits, rounding, zoom, filtering controls.
This separation makes interactions reversible. Changing the palette must not alter a value; zooming must not change the query without an explicit action; and rounding a tooltip must not reduce the value retained for export or comparison.
Validate at Every Boundary
Schema validation catches structural problems, but scientific assertions catch semantic ones.
At ingestion
- Declared dimensions match array shapes.
- Coordinates and parameters remain aligned.
- Fill values are decoded.
- Unit and variable mappings are recognized.
- Raw/adjusted selection uses the matching QC fields.
At publication
- Output contains no unsupported
NaNor infinity values. - Every artifact belongs to one dataset version.
- Required identity and provenance fields are present.
- Counts, depth ranges, and time ranges match a release manifest.
At the API
- Responses conform to the documented schema.
- Parameter names and units are allowlisted.
- Bounds and result limits are enforced.
- Missing values remain
null, not zero or empty strings.
In the browser
- Axis and tooltip units match the payload.
- Missing areas remain visibly missing.
- Time, longitude, and vertical direction are correct.
- A known profile matches an independent pipeline rendering.
Communicate Limitations Without Overloading the Screen
Not every provenance field belongs in a tooltip. Use layers of explanation:
- Put the variable, unit, time, and identity beside the value.
- Link the chart to a concise filtering or methodology note.
- Provide source and processing details on a dedicated data page.
- Keep machine-readable provenance in the API or artifact metadata.
OceanGraph uses this pattern through its Data Source, Data Filtering Policy, and Limitations pages. The interface stays approachable while the scientific rules remain inspectable.
Contract Review Checklist
Before publishing a feature that displays scientific data, ask:
- Can every displayed variable be named unambiguously?
- Is its unit available in the payload and visible in the UI?
- Can missing, rejected, and interpolated values be distinguished where needed?
- Does the selected value use the matching QC decision?
- Can a user identify the observation behind a point?
- Is time serialized unambiguously and longitude normalized deliberately?
- Can the team identify the source snapshot, code, and configuration?
- Does one known observation agree from source file to browser?
If any answer depends on a developer remembering an unwritten convention, the contract is incomplete.
If applying these contracts to an existing ocean-data application would be difficult, the inquiry link below can also be used to ask about design and implementation support.
Contact
Implementation support and annotation services
Ask about setup, design, and implementation support, or annotation services.
Frequently Asked Questions
Should the API return original QC flags?
Return them when the interface or users need that detail. Otherwise, return the selected representation and a versioned policy identifier, while retaining the original flags in the processing trace.
Is null enough to represent all missing states?
It is sufficient for many chart payloads, but keep a reason or availability mask when rejected, unobserved, and unsupported-interpolation states matter to interpretation.
How much precision should JSON keep?
Retain enough precision for the product’s scientific use and document rounding. Format fewer digits for display without repeatedly rounding the stored canonical value.
Can provenance be only a Git commit hash?
No. A commit does not identify the source snapshot, runtime configuration, or published output version. It is one part of a useful provenance record.
