MoonBit CF Ocean Data Exchange and Slicing Tools for NetCDF Classic/64-bit Offset and Oceanographic Data Abstractions
| Area | Supported | Explicit boundary |
|---|---|---|
| NetCDF | Classic (CDF-1) and 64-bit Offset (CDF-2) headers and variable payloads | NetCDF-4/HDF5 containers are not implemented |
| CF metadata | CF-oriented dimensions, attributes, units, standard-name validation | The library does not attempt to validate every CF convention |
| Slicing | Strided 3D/4D index ranges, masked arrays, lazy scaling | Data arrays are represented as flat MoonBit arrays |
| Quality control | Missing, range, rate, spike, and flatline flags with summaries | Rules are deterministic thresholds; they are not a replacement for domain review |
| Profile screening | Depth-ordered temperature/salinity QC with gradients, density inversions, and stable reports | Screening flags do not sort or repair observations and do not replace mission-specific QC |
| Scientific methods | Bounded EOS-80/UNESCO-style and TEOS-10-oriented approximations | Not a complete TEOS-10/GSW thermodynamic implementation; see scientific methods |
| Zarr | Zarr v2 metadata and raw little-endian f8 chunks | Chunks are uncompressed (compressor: null); zlib/Blosc codecs are not included |
| Parquet | Compact JSON schema representation for ocean profiles | This helper does not emit a complete Parquet binary file or Arrow buffers |
| Other exports | CSV, JSON, GeoTIFF metadata, and lineage records | Each helper documents its representation in its package tests |
moon fmt --check
moon check --target all --deny-warn
moon test --target all --deny-warnmoon run cmd/benchmark --target nativemoon add hrwqe/cf_oceanlet dataset = @dataset.OceanDataset::new("cast")
dataset.add_axis(@dataset.CoordinateAxis::new(
"depth",
@dataset.DepthAxis,
"m",
[0.0, 50.0, 100.0],
))
let temperature = @dataset.DatasetVariable::new(
"temperature",
"sea_water_temperature",
"degree_Celsius",
["depth"],
[3],
[21.0, 18.5, 16.0],
)
dataset.add_variable(temperature)
let issues = @dataset.validate_dataset(dataset)let config : @quality.QCConfig = {
fill_value: Some(-999.0),
min_value: Some(-2.0),
max_value: Some(40.0),
max_delta: Some(5.0),
flatline_window: 4,
}
let report = @quality.inspect_series(
"temperature",
[20.1, 20.2, -999.0, 20.0],
config,
)
let masked = @quality.qc_mask([20.1, 20.2, -999.0, 20.0], report, -999.0)let samples = [
@analytics.ProfileQcSample::new(0.0, 20.0, 35.0),
@analytics.ProfileQcSample::new(50.0, 18.5, 35.2),
]
let report = @analytics.scan_ocean_profile_default(samples)
let ready_for_export = report.is_clean()fn inspect_netcdf(bytes : Array[Byte]) -> Unit {
match @binary.parse_nc_header(@binary.ByteBuffer::new(bytes)) {
Some(header) =>
match @binary.read_nc_variable(bytes, header, "temperature") {
Some(values, diagnostics) =>
println("values=" + values.length().to_string() +
", diagnostics=" + diagnostics.length().to_string())
None => println("variable payload is unavailable")
}
None => println("invalid NetCDF header")
}
}src/
├── binary/ NetCDF Classic/CDF-2 buffers, layouts, diagnostics
├── cf/ CF metadata, units, and compliance diagnostics
├── dataset/ axes, grids, profiles, time series, validation, resampling
├── slice/ ranges, 3D/4D indexing, masked and lazy arrays
├── quality/ deterministic observation QC rules and reports
├── analytics/ seawater physics, profile screening, and spatial-temporal calculations
├── benchmark/ reusable deterministic benchmark workloads
├── export/ NetCDF, Zarr v2, CSV, JSON, Parquet-schema helpers
├── lineage/ transformation and provenance records
└── cli/ summaries, validation reports, and benchmark formatting
cmd/benchmark/ executable benchmark entrypointmoon fmt --check
moon check --target all --deny-warn
moon build --target all
moon test --target all --deny-warn --enable-coverage
moon coverage report -f summary
moon infoMoonBit CF Ocean Data Exchange and Slicing Tools for NetCDF Classic/64-bit Offset and Oceanographic Data Abstractions