grib

package module
v0.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 17 Imported by: 0

README

The Go gopher holding a small globe

simple-grib

CI Go Report Card OpenSSF Scorecard Go Reference Go version License Latest tag CGO disabled WASM

English | 简体中文

Pure-Go GRIB edition 1 + 2 reader/writer — zero cgo, no eccodes, no C toolchain. The only non-standard-library module is the pure-Go simple-webp decoder behind the local-use WebP template. Metadata tracks ecCodes key by key, decoded values are bit-exact, and the same code builds to WebAssembly.

f, err := grib.Open("icon.grib2")
if err != nil {
    log.Fatal(err)
}
defer f.Close()

for m, err := range f.Messages() {
    if err != nil {
        log.Fatal(err)
    }
    p, _ := m.Product()
    q, _ := paramdb.QueryFrom(m)
    fmt.Println(p.ParameterName, paramdb.ShortNameOrUnknown(q), paramdb.UnitsOrUnknown(q))
}
// Temperature t K
  • ecCodes-compatible metadata: shortName / name / paramId / units / typeOfLevel / parameterName are answered by the concept chain generated from the vendored ecCodes definitions (local centre → master → ecmf → legacy, ties to master; table 4.2 and table 2 lookups take the message's own table version) — not by a hand-written map.
  • Bit-exact values: CMA LARP four anchors, 442 messages (358M values) + data_snd 11 files, 1109 messages (788.8M values, incl. CCSDS 156/156 and simple packing 69/69) hash-identical to eccodes; JPEG 2000 is cross-checked against Jasper's own decoder.
  • Editions 1 and 2, one API: grib.Open dispatches by edition, GRIB1 keeps native float64 precision (Message.Values64()), and one file may mix both.
  • WASM ready: wasm/ builds grib.wasm plus a browser viewer — no server, no C toolchain (CGO_ENABLED=0 go build ./... passes).

[!NOTE] 🚀 Initial release, canary testing in progress. If you hit any problem, please open an issue!

A sibling project of simple-netcdf.

GRIB1

Landed 2026-10-15. grib.Open dispatches automatically by edition — GRIB1 messages are parsed by the grib1/ package (five sections IS/PDS/GDS/BMS/BDS, IBM-float reference value, sign-magnitude scale factors, bitmap expansion, simple-packed bit stream), reusing the grid-coordinate generators already verified on the GRIB2 side (regular lat/lon, Gaussian, rotated lat/lon, polar stereographic, Lambert conformal, quasi-regular); GRIB1 and GRIB2 messages may be mixed within one file. GRIB1 values keep native float64 precision (Message.Values64()). Product.ParameterName resolves against the vendored per-(centre, table version) table 2 — same selection as ecCodes' grib1/2.[centre].[table2Version].table accessor: table2Version < 128 routes to the WMO tables (the centre segment is ignored), >= 128 uses the message's centre (subCentre == 98 taking over when the centre is not 98), and a missing table or code degrades to the decimal code string exactly like ecCodes' codetable_title; grib1.RegisterTable2 still overrides it.

Features

Capability Status
Multi-message file index + section 0–7 structural parsing and validation (GRIB2) ✅
GRIB1 decoding: five-section parse + values (native float64) + coordinates; mixable with GRIB2 ✅
Metadata: Identification / Product (with WMO code-table names), Walk generic template walker (one parser for all 254 templates) ✅
Grid coordinates: 3.0/3.1/3.2/3.3 (+rotated), 3.40/3.41 Gaussian, 3.20 polar stereographic / 3.30 Lambert conformal point-by-point ✅
Data decoding: 5.0 simple (any bit width), 5.2 complex, 5.3 complex+spatial differencing, 5.4 IEEE binary32, 5.40 JPEG 2000 (pure-Go JPC decoder), 5.41 PNG (grayscale 1/2/4/8/16-bit), 5.42 CCSDS AEC (own codec); 5.49152 carries a WebP image payload (local use, stored verbatim; header/decode via simple-webp) ✅
Bitmap (section 6, indicator 0/255) + declared point count cross-check ✅
Writers: gribw templates 5.0 / 5.4 with round-trip tests, plus 5.41 PNG (SetPNG) and 5.49152 WebP (SetWebP) images; local table registration ✅
Writer gribw1: GRIB1 encoding (simple packing, grid types 0/4 + bitmap + constant fields) ✅
CLI gribdump: metadata / values / field-by-field Walk / JSON / WebP image export ✅
WASM wasm/: decode GRIB1 + GRIB2 directly in the browser / Node; metadata + values + coordinates as TypedArrays, drag-and-drop viewer included ✅

Install

go get github.com/knoweather/simple-grib

Prebuilt gribdump binaries for linux/amd64, linux/arm64, linux/loong64, windows/amd64 and darwin/arm64 are attached to each release.

Quick start

CGO_ENABLED=0 go build ./...
CGO_ENABLED=0 go test -count=1 ./...

go run ./cmd/gribdump sample.grib2 # per-message metadata (with code-table names)
go run ./cmd/gribdump -values 16 sample.grib2 # first 16 decoded values
go run ./cmd/gribdump -section 3 -section 5 sample.grib2 # field-by-field Walk
go run ./cmd/gribdump -json sample.grib2 # machine readable
go run ./cmd/gribdump -webp satellite.webp sample.grib2 # extract a WebP image payload

Examples

Reading: metadata + values + coordinates

package main

import (
	"fmt"

	grib "github.com/knoweather/simple-grib"
)

func main() {
	fl, err := grib.Open("sample.grib2")
	if err != nil { panic(err) }
	defer fl.Close()

	n, _ := fl.NumMessages()
	for i := 0; i < n; i++ {
		m, err := fl.Message(i)
		if err != nil { panic(err) }
		p, err := m.Product()
		if err != nil { panic(err) }

		level := "n/a"
		if p.Level1 != nil {
			level = fmt.Sprintf("type=%d", p.Level1.Type)
			if p.Level1.HasValue {
				level = fmt.Sprintf("type=%d value=%g", p.Level1.Type, p.Level1.Scale)
			}
		}
		forecast := "n/a"
		if p.ForecastTime != nil && !p.ForecastTime.Overflow {
			forecast = p.ForecastTime.Value.String()
		}
		fmt.Printf("msg%d: %s level=%s forecast=%s\n",
			i, p.ParameterName, level, forecast)

		vals, err := m.Values() // data values (5.0/5.2/5.3/5.4/5.40/5.42)
		if err != nil { fmt.Println(" values:", err); continue }
		fmt.Printf(" %d values, first=%.4g\n", len(vals), vals[0])

		g, _ := m.Grid()
		if lat, lon, err := g.Point(0); err == nil {
			fmt.Printf(" point(0) = %.4f, %.4f\n", lat, lon)
		}
	}
}

Writing: simple packing round trip

import (
	grib "github.com/knoweather/simple-grib"
	"github.com/knoweather/simple-grib/gribw"
)

fl, _ := grib.Open("sample.grib2")
m, _ := fl.Message(0)
g, _ := m.Grid()
vals, _ := m.Values()

msg := gribw.New()
_ = msg.SetDiscipline(0)
_ = msg.SetIdentification(id) // *grib.Identification
_ = msg.SetGrid(g) // reuse the reader's grid definition
_ = msg.SetProduct(prod) // *grib.Product

sec5, payload, _ := gribw.EncodeSimple(vals, gribw.SimpleParams{R: 0, E: 4, D: 1, Bits: 10})
_ = msg.SetDataSection(sec5, payload)
data, _ := gribw.File(msg) // complete GRIB2 byte stream (variadic: multiple messages)

WebP image payload (local use)

GRIB can also carry an image product: template 5.49152 stores a complete WebP file verbatim — the library neither decodes pixels on write nor re-encodes values into an image. Values() reports pack.ErrNotNumeric for such messages; use the image accessors instead.

webp, _ := os.ReadFile("satellite.webp")

msg := gribw.New()
_ = msg.SetDiscipline(0)
_ = msg.SetIdentification(id)
_ = msg.SetGrid(g)
_ = msg.SetProduct(prod)
_ = msg.SetWebP(webp)   // section 5 = 11-byte header, section 7 = the file verbatim
data, _ := gribw.File(msg)

m, _ := fl.Message(0)   // reader side
raw, _ := m.WebP()      // identical bytes back
info, _ := m.WebPInfo() // {Width, Height, Lossless, Animated}; header only
img, _ := m.WebPImage() // decoded image.Image (first frame if animated)

WASM (browser / Node)

Pure Go + zero CGO means it builds to WebAssembly as-is: decode GRIB2 from a byte stream in the frontend — data never leaves the browser, no backend needed. Entry point in wasm/.

GOOS=js GOARCH=wasm CGO_ENABLED=0 go build -o wasm/grib.wasm ./wasm
cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" wasm/ # glue must match the Go version
cd wasm && python3 -m http.server 8000 # open http://localhost:8000/viewer.html

To skip the server step, build a single-file bundle (inlined glue + gzipped wasm ≈ 1.9 MB, just double-click it):

go run ./wasm/tools/mkstandalone -html wasm/viewer.html -wasm wasm/grib.wasm \
 -glue "$(go env GOROOT)/lib/wasm/wasm_exec.js" -out wasm/viewer.standalone.html
const res = simpleGrib.decode(new Uint8Array(await file.arrayBuffer()),
 { values: true, points: true, perPoint: true });
res.messages[0].product.parameterName; // "Temperature"
res.messages[0].values; // Float32Array
res.messages[0].grid.lats; // Float64Array (same order as values with perPoint)

wasm/viewer.html is a ready-made single-file viewer: drop a .grib2 and see results — message list, identification/product/grid metadata (code-table names resolved on the Go side), value-field rendering (regular grids draw a raster, projected grids draw a scatter with hover readouts), first 200 rows as a value table, plus CSV / PNG / metadata JSON export.

Measured compatibility: GOOS=js GOARCH=wasm go build ./... passes clean for every package, and CI runs the whole suite under Node on Linux. Coordinate anchors are gated per platform: the packed-float64 digests stay bit-exact on the recorded amd64 and darwin/arm64 builds, while other platforms (wasm, other GOARCH or GOAMD64 variants) must reproduce 192 sampled points within 1e-9°. Host-only checks — spawning a native go build and fuzzing — skip on js/wasm; js/wasm under a Windows host still cannot list directories (Linux hosts can). Item-by-item evidence in wasm/README.md.

Performance comparison

Measured on an AMD 4C Debian 13 box (go1.24.4 vs system eccodes 2.41.0), corpus = 47 real files from 10 families (CMA LARP TRAMS/GRAPES, ECMWF ICON/agl/atmosphere, GFS pgrb2, JMA GPV, CCSDS, pangu, …). Protocol: one warmup pass + 10 timed rounds averaged per engine; one round = open the file + call Values() on every message. Driver and protocol in bench/p7_decode_bench/.

The 42 files both engines can decode (350.13 MB / 485,311,281 values / 1030 messages):

Family Files Size simple-grib (Go) eccodes (C) Notes
JPEG 2000 (5.40) CMA LARP 4 153.3 MB 3.5 MB/s 9.3 MB/s pure-Go JPC decoder vs Jasper C — currently the main gap
Simple packing, large files ICON/pangu 5 139.1 MB 681 MB/s 678 MB/s on par (≈1.00×)
GFS pgrb2 multi-field 3 34.4 MB 453 MB/s 229 MB/s Go ≈2.0× faster
JMA GPV multi-field 9 19.5 MB 246 MB/s 428 MB/s eccodes ≈1.7× faster (incl. a multi-field-slice protocol difference)
ECMWF small files (agl/atmosphere/CCSDS…) 21 3.8 MB 326 MB/s 74 MB/s Go ≈4.4× faster (per-message overhead path)
Total 42 350.1 MB 8.0 MB/s · 11.1M val/s 20.7 MB/s · 28.7M val/s overall throughput: eccodes ≈2.6× (dragged down by the JPC files)

fail-loud evidence on the mixed corpus (before GRIB1 landed): all 5 non-GRIB2 files were rejected with context — GRIB edition 1 ×2, BUFR ×2 (magic BUFR), zero-byte truncation ×1; failed files are never silently dropped, they are reported along with the results. (GRIB1 is now supported; edition 3 / BUFR are still rejected this way.)

To reproduce (from the repo root):

CGO_ENABLED=0 go run ./bench/p7_decode_bench --rounds 10 <files...> > go_results.jsonl
python3 -u bench/p7_decode_bench/eccodes_bench.py --rounds 10 <files...> > py_results.jsonl

Protocol notes: the simple-grib column is the pure data-values path (lazy coordinate generation is not counted); eccodes calls the C API per message through its Python binding (wrapper overhead inside the timed path); the JMA GPV multi-field wrap decodes against prebuilt per-field slices on the eccodes side (that binding build has no next-message API).

Design

Key principles (spec-as-data / parse–interpret split / three-layer separation / graceful degradation / symmetric write):

  1. Spec-as-data — the WMO CSVs plus the vendored ecCodes definitions (see paramdata/PROVENANCE.txt) are the single source of truth; cmd/specgen generates spec/tables_gen.go + templates_gen.go + paramname_gen.go (the versioned 4.2 title pool), cmd/paramgen generates the concept / MARS / GRIB1 table-2 data (paramdb/concepts_gen.go, paramdb/mars_gen.go, grib1/mars_gen.go, grib1/table2_gen.go, mars_gen.go), and both have -check drift detection; every WMO/ecCodes revision = re-sync + regenerate, with an auditable workflow.
  2. Parse–interpret split — one generic template engine (Walk) parses all 254 templates from the generated descriptors; semantic interpretation (grid coordinates, packing decode) is implemented per template number only where needed; unimplemented parts expose raw fields instead of failing.
  3. Three-layer separation — L1 wire format (sections/bytes/bits) → L2 structure (templates/code tables, pure data) → L3 semantics (grid/pack/Product); each layer testable in isolation.
  4. Graceful degradation is a first-class citizen — unknown template numbers, local-use values → typed accessors return contextual errors; raw fields are always reachable; never panics.
  5. Symmetric writing — the same TemplateDef descriptors drive both reading and writing (gribw), so two structural definitions cannot drift.
L3 semantics grid/ (grid → coords) pack/ (data representation → values, registry + built-in decoders) (root) Product/Identification
L2 structure spec: WMO CSV ──specgen──► Go tables/template descriptors; Table.Lookup / Template / Walk
L1 wire format File (io.ReaderAt + message index) → Message (whole-message buffer) → Section (zero-copy slices); big-endian reads / BitReader

Correctness

  • Real-corpus bit-level comparison: CMA LARP four-anchor 442 messages (358M values) + data_snd 11 files 1109 messages (788.8M values, including CCSDS 156/156 and simple packing 69/69) match eccodes point-by-point on SHA-256; JPEG 2000 additionally cross-checked against Jasper's own decoder.
  • eccodes binary comparison vectors (testdata/ecc-xcheck/): simple packing 576/576, IEEE 108/108 (incl. ±Inf/NaN/subnormals), regular/Gaussian/rotated grids point-by-point max diff = 0 / 4.26e-14° / 9.9e-7°.
  • CCSDS 5.42 oracle: 36/36 PASS (scripts/xcheck/ccsds-oracle.sh, digest anchors in the script header comments).
  • PNG 5.41 cross-checks: encoder-independent fixtures from pypng, Pillow and the sister library simple-png (1/2/4/8/16-bit plus Adam7), and 500 randomized 1/2/4/8/16-bit SetPNG outputs decoded by simple-png — every sample matches.

Known limitations

  • Data templates 5.1 / 5.5x spectral / 5.200 run-length → pack.ErrUnsupported (fail-loud)
  • JPEG 2000 5.40: reversible 5/3 transform, LRCP order, one layer and one component only; irreversible 9/7, multi-layer / multi-component codestreams and COC/QCC/RGN/POC/PPM/PPT/SOP/EPH markers → pack.ErrJPCUnsupported
  • PNG 5.41: grayscale only, bit depth 1/2/4/8/16 and equal to bitsPerValue; colour, transparent and palette PNGs → fail-loud. SetPNG encodes a grayscale image from values; a pre-encoded PNG can still be installed with SetDataSection
  • Local-use template 49152 (WebP) is an opaque image payload: stored and returned byte-for-byte by SetWebP/WebP, and Values reports pack.ErrNotNumeric. Lossy and animated files are accepted (WebPImage returns the first frame for animations); the image size need not match the grid, because numberOfValues records the pixel count
  • IEEE 5.4 only precision=1 (binary32); 64/128-bit → fail-loud
  • Bitmap indicator 1–254 (centre-defined) → fail-loud
  • Grids: remaining projection templates (3.10/3.12/3.31…) and stretched Gaussian (3.42/3.43) are metadata-only; Point/Lats/Lons → grid.ErrNotImplemented
  • Writers currently support 5.0 / 5.4(precision=1) (GRIB2), the 5.41 PNG (SetPNG, grayscale 1/2/4/8/16-bit) and local-use 5.49152 WebP image (SetWebP); and gribw1: GRIB1 simple packing (grid types 0/4, bitmap, constant fields; round-trip verified against real files); BUFR is only recognised and rejected

Documentation

Doc Contents
wasm/README.md WASM entry: build, JS API, browser viewer, measured cross-arch compatibility
bench/p7_decode_bench/README.md benchmark driver and protocol

AI powered

Model credits:

Credits

The Go gopher was designed by Renee French and is licensed under CC BY 3.0. The logo in docs/logo.svg is a derivative work based on that design.

Documentation

Overview

Package grib 提供纯 Go 实现的 WMO GRIB 第 2 版(GRIB2)消息读取器。

它可以读取包含多条首尾相接消息的文件,校验节结构(第 0-7 节,以及 以 "7777" 结尾的第 8 节),并以类型化方式访问标识段、网格定义段、产品 定义段、数据表示段与解码后的要素值。模板布局来自 spec 包(由 WMO 官方 CSV 文件生成);网格坐标计算在 grid 包,数值解包在 pack 包。

该读取器遵循"失败即报错"(fail-loud)原则:任何结构性违规必定返回错误, 绝不猜测绕过。未知模板或本地使用模板会降级为仅元数据访问 (Section.Data / Raw 视图),不会阻断消息其余部分的读取。

Package grib is a pure-Go reader for WMO GRIB edition 2 (GRIB2) messages.

It reads files containing multiple concatenated messages, validates the section structure (sections 0-7 plus the "7777" end section, section 8), and provides typed access to the identification, grid definition, product definition, data representation, and decoded values. Template layouts come from the spec package (generated from the official WMO CSV files); grid coordinate math lives in grid, value unpacking in pack.

The reader is fail-loud: structural violations always return an error and are never guessed around. Unknown or local-use templates degrade to metadata-only access (Section.Data / Raw views) without blocking the read of the rest of the message.

Example

Example is the README quick-start, kept compilable so the docs cannot drift: open a file, walk its messages, and read the ecCodes-compatible parameter names (Product.ParameterName is the table 4.2 title; paramdb answers the shortName / units keys). The corpus is the 187-byte ECMWF test file in this repository, so the output is deterministic.

f, err := grib.Open("testdata/p6-a-xcheck/p6a_ll_1xn.grib2")
if err != nil {
	log.Fatal(err)
}
defer f.Close()

for m, err := range f.Messages() {
	if err != nil {
		log.Fatal(err)
	}
	p, err := m.Product()
	if err != nil {
		log.Fatal(err)
	}
	q, err := paramdb.QueryFrom(m)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(p.ParameterName, paramdb.ShortNameOrUnknown(q), paramdb.UnitsOrUnknown(q))
}
Output:
Temperature t K

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotGRIB2 reports a bad 'GRIB' magic — the file is not GRIB at all.
	// (The name is kept for backward compatibility; it is now used only for
	// magic mismatches.)
	//
	// ErrNotGRIB2 报告 'GRIB' 魔数不匹配——该文件根本不是 GRIB。
	// (名称保留以兼容旧代码;现在仅用于魔数校验失败。)
	ErrNotGRIB2 = errors.New("grib: not a GRIB message")
	// ErrUnsupportedEdition reports the right magic but an edition that is
	// neither 1 nor 2. This package supports GRIB edition 1 (FM 92-IX) and
	// edition 2 (FM 92-XIII); editions 0 and 3+ are rejected here.
	//
	// ErrUnsupportedEdition 报告魔数正确、但版本号既不是 1 也不是 2。本包
	// 支持 GRIB 第 1 版(FM 92-IX)与第 2 版(FM 92-XIII);版本 0 及 3 以上
	// 在此被拒绝。
	ErrUnsupportedEdition = errors.New("grib: unsupported GRIB edition")
	// ErrTruncated reports a file that ends inside a message or a section.
	//
	// ErrTruncated 报告文件在某条消息或某个节的中途结束。
	ErrTruncated = errors.New("grib: truncated")
	// ErrBadSectionLength reports a section length field that disagrees with
	// the actual bytes (too small, or past the end of the message).
	//
	// ErrBadSectionLength 报告节长度字段与实际字节数不符(过小,或越过消息
	// 末尾)。
	ErrBadSectionLength = errors.New("grib: bad section length")
)

Sentinel errors for file-level and section-level problems. Classify with errors.Is; retrieve the offending number with errors.As via *ErrSectionAbsent or *ErrUnknownTemplate.

文件级与节级问题的哨兵错误。用 errors.Is 分类;用 errors.As 配合 *ErrSectionAbsent 或 *ErrUnknownTemplate 取出出错的编号。

Functions

This section is empty.

Types

type Calendar

type Calendar struct {
	TemplateNumber int // 模板号 octet 22-23,表 1.5(0=日历定义,2=日历+古气候偏移) / template number octets 22-23, table 1.5 (0 = calendar definition, 2 = calendar + paleoclimate offset)
	TypeOfCalendar int // 模板内容 octet 24,表 1.6(0=Gregorian,1=360 天,…),缺失时为 0 / template content octet 24, table 1.6 (0 = Gregorian, 1 = 360-day, ...); 0 when absent
}

Calendar 是第 1 节(octet 22 起)携带的可选日历定义。

Calendar is the optional calendar definition carried in section 1 (octets 22+).

type Chemical

type Chemical struct {
	ConstituentType                   int // table 4.230, or the 4.233/CCT-14 aerosol type
	AerosolType                       int // alias of ConstituentType on aerosol templates; -1 otherwise
	SourceSinkChemicalPhysicalProcess int // table 4.238; -1 absent

	TypeOfSizeInterval      int // table 4.91, size interval; -1 absent
	ScaleFactorOfFirstSize  ScaledField
	ScaledValueOfFirstSize  ScaledField
	ScaleFactorOfSecondSize ScaledField
	ScaledValueOfSecondSize ScaledField

	TypeOfWavelengthInterval      int // table 4.91, wavelength interval; -1 absent
	ScaleFactorOfFirstWavelength  ScaledField
	ScaledValueOfFirstWavelength  ScaledField
	ScaleFactorOfSecondWavelength ScaledField
	ScaledValueOfSecondWavelength ScaledField
}

Chemical carries the section-4 chemistry and aerosol keys. They exist only on the templates that WMO dedicates to atmospheric chemical constituents, aerosols and optical properties (4.40–4.50, 4.57–4.85, 4.108–4.111 and 4.124–4.199). A negative interval/type field means the template has no such field.

type DataRep

type DataRep struct {
	TemplateNumber int // octets 10-11
	NumValues      int // octets 6-9: expected output length after the bitmap
	Fields         *spec.Walk
}

DataRep is the parsed section 5: the expected value count and the data representation template number, plus (for WMO-defined templates) a Walk over the template fields. Fields is nil for local/unknown templates; in that case Values() fails in the pack layer with a clear error.

type ErrSectionAbsent

type ErrSectionAbsent struct{ Number int }

ErrSectionAbsent reports a required section number missing from a message. ErrSectionAbsent 报告消息中缺少某个必需的节号。

func (*ErrSectionAbsent) Error

func (e *ErrSectionAbsent) Error() string

type ErrUnknownTemplate

type ErrUnknownTemplate struct {
	Section int
	Number  int
}

ErrUnknownTemplate reports a template number with neither a WMO definition nor a local registration (local-use range, or unassigned). Metadata-only access still works; registering a definition with spec.RegisterLocalTable enables Walk-based parsing and name display.

ErrUnknownTemplate 报告某个模板号既无 WMO 定义也无本地注册(处于本地使用 区间或尚未分配)。此时仍可做仅元数据访问;用 spec.RegisterLocalTable 注册 定义后即可启用基于 Walk 的解析与名称显示。

func (*ErrUnknownTemplate) Error

func (e *ErrUnknownTemplate) Error() string

type ErrUnsupportedBitmap

type ErrUnsupportedBitmap struct{ Indicator int }

ErrUnsupportedBitmap reports a section 6 bitmap indicator the reader cannot handle: indicators 1-253 (a bitmap predetermined by the centre, not present in the section) and 254 (bitmap defined earlier in the same message). Only indicator 0 (bitmap right here) and 255 (no bitmap) are supported.

func (*ErrUnsupportedBitmap) Error

func (e *ErrUnsupportedBitmap) Error() string

type File

type File struct {
	// contains filtered or unexported fields
}

File 表示一个已打开的 GRIB 文件(版本 1 或 2,可能混合),其消息索引在 打开时建立。索引只读取第 0 节头部,因此打开多消息大文件开销很小;消息 正文按需延迟读取。

File 支持混合文件:每条消息按其自身版本解析,返回的 Message 用 Message.Edition() 区分。数据服务常把 GRIB1 与 GRIB2 产品放在同一目录。

File is an open GRIB file (edition 1 or 2, possibly mixed) whose message index was built at open time. The index reads only the section 0 headers, so opening a large multi-message file is cheap; message bodies are read lazily on demand.

File supports mixed files: each message is parsed by its own edition and the returned Messages are told apart with Message.Edition(). Data services routinely keep GRIB1 and GRIB2 products in the same directory.

func Open

func Open(path string, opts ...Option) (*File, error)

Open 打开 path 并扫描其 GRIB 消息索引。返回的 File 必须关闭(通常用 defer)。

Open opens path and scans its GRIB message index. The returned File must be closed (typically with defer).

func OpenReader

func OpenReader(r io.ReaderAt, size int64, opts ...Option) (*File, error)

OpenReader 包装一个已知大小的现有 io.ReaderAt(例如内存缓冲区)。 所有权仍归调用方;这类文件的 File.Close 是空操作。

OpenReader wraps an existing io.ReaderAt of known size (e.g. an in-memory buffer). Ownership stays with the caller; File.Close is a no-op for such files.

func (*File) Close

func (f *File) Close() error

Close releases the underlying file handle. Calling it twice is safe, and it does nothing for files opened via OpenReader.

func (*File) Message

func (f *File) Message(i int) (*Message, error)

Message returns message i (0-based), reading its full body from the underlying reader and validating the section structure. For a multi-field envelope, index i selects one data-field group: the returned message is the virtual view [s0][s1][s3][that group's sections] (assembled contiguously), and its Size() reports the envelope's declared totalLength.

func (*File) Messages

func (f *File) Messages() iter.Seq2[*Message, error]

Messages iterates all messages in file order. An error terminates the iteration; when a yielded message is non-nil the error is necessarily nil.

func (*File) NumMessages

func (f *File) NumMessages() (int, error)

NumMessages returns the number of logical messages in the file (known at open time). It never fails for an open File.

func (*File) ValuesAll

func (f *File) ValuesAll(workers ...int) ([][]float32, error)

ValuesAll decodes every message in the file and returns one []float32 per message in file order. The worker count is optional:

  • f.ValuesAll() — sequential decoding (default, workers=1, no goroutines)
  • f.ValuesAll(n), n>1 — decode with at most n concurrent goroutines

Semantics: n <= 1 selects the sequential default; n greater than the message count is clamped to it; more than one argument is a programming error and returns an error (fail-loud). For automatic parallelism pass runtime.GOMAXPROCS(0) explicitly — there is no implicit magic.

Concurrency safety: io.ReaderAt is required to be goroutine-safe; each worker builds its own Message from a freshly read buffer, and a Message is immutable after construction. Do not call pack.Register concurrently while ValuesAll is running (the unpacker registry is shared global state).

Memory: all decoded results are held simultaneously (e.g. a pangu file with 69 messages / 71.6M values is about 287 MB of float32). For a streaming footprint use Messages() + Values() instead.

Errors: the error of the first failing message in file order is returned (the same error a sequential walk would hit at the same position); other messages are not reported individually. Bit-exactness with the sequential path is pinned by TestA_P8A_ParallelValuesBitExact.

type ForecastTime

type ForecastTime struct {
	Unit     int
	Raw      uint32        // original count in units of Unit (template 4.0 octets 19-22)
	Value    time.Duration // Raw × unit; saturates at MaxInt64 on overflow
	Overflow bool          // true when Value saturated
}

ForecastTime is the forecast-time part of a product definition. Unit is a table 4.4 code (0 = minutes, 1 = hours, 2 = days, 3 = months, 4 = years, ...); Raw is the stored count as-is, and Value converts Raw to a duration for units 0-2. For units >= 3 (months/years/...) there is no fixed length, so Value stays 0 and callers must interpret Unit themselves.

Raw counts whose true duration exceeds time.Duration (about 292 years) saturate Value at MaxInt64 and set Overflow — the previous implementation let the multiplication wrap silently into a negative duration (bug.md §2.2).

type Identification

type Identification struct {
	// Edition 是消息的 GRIB 版本(1 或 2)。GRIB1 按 GRIB1 第 1 节布局解析;
	// ProductionStatus / TypeOfProcessedData 仅属 GRIB2,GRIB1 时为 -1。
	//
	// Edition is the message's GRIB edition (1 or 2). GRIB1 follows the
	// GRIB1 section 1 layout; ProductionStatus / TypeOfProcessedData are
	// GRIB2-only concepts and are -1 for GRIB1.
	Edition             int
	Centre              int       // 中心号 octets 6-7,表 CCT-11 / centre octets 6-7, table CCT-11
	SubCentre           int       // 子中心 octets 8-9 / sub-centre octets 8-9
	CentreName          string    // CCT-11 表中 Centre 的名称;代码不在表中时为 "" / CCT-11 name of Centre; "" when the code is not in the table
	MasterTableVersion  int       // 主表版本 octet 10 / master table version octet 10
	LocalTableVersion   int       // 本地表版本 octet 11 / local table version octet 11
	ReferenceTime       time.Time // UTC / UTC
	ProductionStatus    int       // 生产状态 octet 20,表 1.3(0=业务) / production status octet 20, table 1.3 (0 = operational)
	TypeOfProcessedData int       // 处理数据类型 octet 21,表 1.4(0=分析) / type of processed data octet 21, table 1.4 (0 = analysis)
	Calendar            *Calendar // 第 1 节未携带日历定义时为 nil / nil when section 1 carries no calendar definition
}

Identification 是解析后的第 1 节。ReferenceTime 为 UTC 参考时间; 对预报产品而言即分析(起报)时间。

Identification is the parsed section 1. ReferenceTime is the reference time in UTC; for forecast products it is the analysis (initialization) time.

type Level

type Level struct {
	Type     int
	Scale    float64 // decoded level value; meaningful only when HasValue is true
	HasValue bool    // false when the scaled-value octets are missing (all ones) — WMO Note 168 / ecCodes can_be_missing: this type carries no numeric level

	// ScaleFactorRaw / ScaledValueRaw are the untouched section bytes: the
	// sign-magnitude scale-factor octet (0xFF = missing) and the 4-octet
	// scaled value (0xFFFFFFFF = missing). Callers reproducing ecCodes'
	// per-key view of a surface (scaleFactorOfFirstFixedSurface /
	// scaledValueOfFirstFixedSurface, which the parameter concepts condition
	// on) need the pair, not the decoded Scale: (0, 2) and (1, 20) decode to
	// the same value but are different keys.
	ScaleFactorRaw uint8
	ScaledValueRaw uint32
}

Level is one fixed surface of a product definition: Type is a table 4.5 code (e.g. 1 = isobaric surface (Pa), 3 = height above ground), Scale the decoded value obtained by applying the WMO scale factor to the raw integer (e.g. type 1 with scale factor 0 and raw 850 → 850 hPa).

ScaleFactorRaw / ScaledValueRaw keep the raw section bytes so callers that must reproduce ecCodes' per-key view (scaleFactorOfFirstFixedSurface / scaledValueOfFirstFixedSurface, which the parameter concepts condition on) can: (0, 2) and (1, 20) decode to the same Scale but are different keys.

type MarsLabelling

type MarsLabelling struct {
	Class                   int    // marsClass,mars/class.table 的号
	Type                    int    // marsType,mars/type.table 的号
	Stream                  int    // marsStream,mars/stream.table 的号
	ExperimentVersionNumber string // experimentVersionNumber,4 个字符
}

MarsLabelling 是 ECMWF 的 MARS 标签(ecCodes 的 mars_labeling.def):GRIB 里 传的是整数 code,ecCodes 的 marsClass/marsType/marsStream 对外另给一个缩写 token(od/fc/enfo …),由 mars/*.table 映射。

这些标签只对声明了它们的消息存在,因此 MarsLabelling 返回 ok=false 而不是 零值——调用方不能把零值当真实标签用。

MarsLabelling is ECMWF's MARS labelling (ecCodes' mars_labeling.def). It is present only for messages whose centre/local-definition combination declares it, hence the ok result.

type Message

type Message struct {
	// contains filtered or unexported fields
}

Message 表示一条已解析的 GRIB 消息:原始消息体加上校验过的节列表。它同时 承载第 1 版与第 2 版消息——用 Edition() 区分版本,用 GRIB1() 获取 GRIB1 原生视图(GRIB1 独有字段的入口)。

Message 由 File.Message 构造;所有访问器都是只读的,且在构造完成后 消息不可变,可安全地跨 goroutine 共享。

跨版本的语义差异在各访问器处逐一说明。总原则:两个版本共有的概念返回共 有值;某个版本不存在的概念返回显式的"不适用"标记,绝不伪造一个看起来像 真实数据的默认值。

Message is a parsed GRIB message: the raw message body plus a validated section list. It carries both edition 1 and edition 2 — tell them apart with Edition() and get the GRIB1-native view via GRIB1() (the entry point for GRIB1-only fields).

Constructed via File.Message; all accessors are read-only and safe to share across goroutines (the message is immutable after construction).

Cross-edition semantic differences are documented per accessor. The general rule: common concepts get the common value; a concept that does not exist in the edition gets an explicit "not applicable" marker, never a fabricated default that looks like real data.

func (*Message) DataRep

func (m *Message) DataRep() (*DataRep, error)

DataRep parses section 5 (missing → *ErrSectionAbsent). A section too short to carry its fixed header (numberOfValues at octets 6-9, the template number at octets 10-11) is rejected here instead of silently yielding zero values (bug.md §2.4).

func (*Message) Discipline

func (m *Message) Discipline() int

Discipline 返回 WMO 学科代码(GRIB2 第 0 节第 7 八位组,表 0.0),例如 0 表示由大气数据导出的产品。

GRIB1 没有该字段(GRIB1 只承载气象产品);沿用 ecCodes 的 GRIB1→GRIB2 转换约定返回 0——这是有定义的映射,而不是占位值。

Discipline is the WMO discipline code (GRIB2 section 0 octet 7, table 0.0), e.g. 0 = products derived from atmospheric data.

GRIB1 has no such field (GRIB1 carries only meteorological products); following ecCodes' GRIB1→GRIB2 conversion convention it returns 0 — a defined mapping, not a placeholder.

func (*Message) Edition

func (m *Message) Edition() int

Edition 返回 GRIB 版本号:1 或 2。

Edition returns the GRIB edition: 1 or 2.

func (*Message) GRIB1

func (m *Message) GRIB1() (*grib1.Message, bool)

GRIB1 返回 GRIB1 原生视图(表版本号、十进制比例因子、时间范围指示符、 生成过程标识、位图——GRIB2 中不存在的字段都在这里)。对第 2 版消息返回 (nil, false)。

GRIB1 returns the GRIB1-native view (table versions, decimal scale factor, time-range indicator, generating-process id, bitmap — the fields absent from GRIB2 all live there). For an edition-2 message it returns (nil, false).

func (*Message) Grid

func (m *Message) Grid() (*grid.Definition, error)

Grid parses the section 3 grid definition (delegated to the grid package).

func (*Message) Identification

func (m *Message) Identification() (*Identification, error)

Identification parses section 1. The fixed layout follows the WMO template 1.0 definition; the optional calendar part (octets 22+) follows table 1.5. The reference time is validated before use so time.Time normalization can never silently shift an out-of-range date.

func (*Message) Index

func (m *Message) Index() int

Index 返回本消息在其文件中的位置,从 0 开始计数。

Index is this message's 0-based position in its file.

func (*Message) MarsLabelling

func (m *Message) MarsLabelling() (*MarsLabelling, bool)

MarsLabelling 返回消息携带的 MARS 标签。

是否有标签,判据与 ecCodes 的本地定义分派一致:

GRIB2 —— grib2/section.2.def 在 grib2LocalSectionNumber != 0 时按
  grib2/local.[centreForLocal].def 取模板;只有这些模板(含其 template
  引用)声明了 marsClass 码表,集合见 mars_gen.go。
GRIB1 —— grib1/section.1.def:248-277 在 centre 或 subCentre 为 ECMWF 时
  按 grib1/local.98.[localDefinitionNumber].def 取模板;集合见
  grib1/mars_gen.go。判定在 grib1 包内完成。

字段位置来自 grib2/mars_labeling.def:marsClass / marsType / marsStream 各 2 字节大端,experimentVersionNumber 4 字节。section 2 的前 7 个 octet 是 section 2 自身与 grib2LocalSectionNumber,所以 marsClass 落在 octet 8。

func (*Message) Offset

func (m *Message) Offset() int64

Offset 返回消息起点在其文件中的字节偏移。

Offset is the byte offset of the message start in its file.

func (*Message) Product

func (m *Message) Product() (*Product, error)

Product parses section 4.

func (*Message) Section

func (m *Message) Section(n int) (*Section, error)

Section 返回编号为 n 的节(使用当前版本的编号体系),找不到时返回 *ErrSectionAbsent。返回的 Section 的 Data 切片与消息共用底层数组,应按只读 方式使用。

Section returns the section with the given number (in the current edition's numbering), or *ErrSectionAbsent. The returned Section's Data slice shares the message's backing array; treat it as read-only.

func (*Message) Sections

func (m *Message) Sections() []int

Sections 按消息内顺序列出实际出现的节号。

节号是各版本自己的:GRIB2 使用 0-7(以 "7777" 结尾的结束节不对外暴露), GRIB1 使用 0=IS、1=PDS、2=GDS、3=BMS、4=BDS、5=结束标记。同一节号在两个 版本中含义不同(例如 2 在 GRIB2 中是本地使用段,在 GRIB1 中是网格描述 段),因此跨版本遍历前先检查 Edition()。

Sections lists the section numbers actually present, in message order.

The numbers are each edition's own: GRIB2 uses 0-7 (the "7777" end section is not exposed), GRIB1 uses 0=IS, 1=PDS, 2=GDS, 3=BMS, 4=BDS, 5=end marker. The same number means different things in the two editions (e.g. 2 is local use in GRIB2 but the grid description section in GRIB1), so check Edition() before iterating across editions.

func (*Message) Size

func (m *Message) Size() int

Size 返回消息总长度(字节)。

Size is the message total length in bytes.

func (*Message) Step

func (m *Message) Step() (time.Duration, bool)

Step returns the forecast step — end − reference time, the duration ecCodes calls "step". For an instantaneous product StepRange returns begin == end and this is 0. ok=false has the same meaning as in StepRange.

func (*Message) StepRange

func (m *Message) StepRange() (begin, end time.Time, ok bool)

StepRange returns the message's forecast interval as two absolute times, mirroring what ecCodes reports as the forecastTime / step / validityDate triple:

begin = reference time + forecastTime   (interval start; ecCodes "forecastTime")
end   = interval end                    (ecCodes "step" = end − reference time, "validityDate")

For instantaneous messages begin == end. For WMO statistical templates (GRIB2 4.8-4.14) the interval is delimited by the template's "time of end of overall time interval" timestamp — the table 4.4 forecast-time field only marks the *start*, so reading it alone under-reports the step by a whole interval (6h accumulations would read step=0, validity 6h early). For GRIB1 the interval is decoded from the P1/P2 pair under WMO table 5 semantics by the grib1 package.

ok is false when the product has no forecast-time field at all, when the time unit has no fixed duration (months, years — callers have to interpret Unit/Raw themselves, same rule as Product.ForecastTime), or on a parse error. It is never false merely because the interval end is absent: that only happens for instantaneous products, which report begin == end.

oks false vs "no end known": a GRIB2 message whose end-of-interval timestamp is parametrized (templates 4.34/4.114/…, see spec.EndIntervalParametrized) reports begin == end — its interval length cannot be recovered from section 4 alone.

func (*Message) Values

func (m *Message) Values() ([]float32, error)

Values decodes all data values of the message in scan order. It ties together the grid point count, the section 5 value count, an optional section 6 bitmap, and the pack registry:

  • the grid point count comes from the section 3 definition;
  • with a bitmap (indicator 0), its popcount over the first GridPoints bits must equal NumValues, otherwise it is an error;
  • without a bitmap (no section 6, or indicator 255), NumValues must equal the grid point count, otherwise it is an error;
  • the section 7 payload (from octet 6) is handed to pack.Unpack.

Messages that carry the local-use WebP image template (5.49152) have no numeric values: Values returns *pack.ErrNotNumeric — use WebP, WebPInfo or WebPImage instead.

func (*Message) Values64

func (m *Message) Values64() ([]float64, error)

Values64 returns the data values at float64 precision.

For GRIB1 this is native precision: the reference value is an IBM float (24-bit mantissa) and the formula (R + X·2^E)·10^(−D) is evaluated in float64 — a direct downcast to float32 would lose significant digits. For GRIB2 the values are already IEEE binary32; widening them here neither adds nor removes precision (use Values for native precision).

func (*Message) WebP added in v0.0.4

func (m *Message) WebP() ([]byte, error)

WebP 原样返回消息携带的 WebP 文件字节(第 7 段第 6 八位组起)。不做任何 解析或重编码,因此写回的内容与写入时逐字节相同;返回的是副本,调用方可以 安全保留或修改。

WebP 只适用于数据表示模板 5.49152 的消息;其它模板返回错误。

WebP returns the WebP file bytes carried by the message (section 7, from octet 6) without parsing or re-encoding, so the bytes are identical to what was written. The returned slice is a copy the caller may retain or modify.

WebP applies only to messages with data-representation template 5.49152; other templates produce an error.

func (*Message) WebPImage added in v0.0.4

func (m *Message) WebPImage() (image.Image, error)

WebPImage 用 simple-webp 解码消息携带的 WebP,返回 image.Image。有损与无损 码流都接受;动画文件返回合成后的第一帧(simple-webp 的行为),需要逐帧时 请直接用 WebP 取原始字节后交给 simple-webp 的动画 API。

WebPImage decodes the message's WebP with simple-webp and returns an image.Image. Both lossy and lossless bitstreams are accepted; for an animated file the composited first frame is returned (simple-webp's behaviour) — use WebP to get the raw bytes and drive simple-webp's animation API when every frame matters.

func (*Message) WebPInfo added in v0.0.4

func (m *Message) WebPInfo() (WebPInfo, error)

WebPInfo 读取消息的 WebP 容器头:宽、高、是否有损、是否动画。它不解码 像素,因此对大图也很便宜;载荷不是合法 WebP 时返回解析错误。

WebPInfo reads the message's WebP container header: width, height, lossless or lossy, animated or still. It decodes no pixels, so it stays cheap for large images; an invalid payload produces a parse error.

type Option

type Option func(*fileConfig)

Option customizes File behavior. Options are applied at open time and carried by the File into every message it parses.

Option 定制 File 的行为。选项在打开文件时生效,并随 File 传递到其解析的 每一条消息。

func WithLenientEndSection

func WithLenientEndSection() Option

WithLenientEndSection relaxes the section 8 end-marker check: up to 4 trailing bytes after section 7 are accepted whatever their content, instead of requiring the standard "7777". Use only for producers known to emit non-standard trailers; the default is strict mode.

WithLenientEndSection 放宽第 8 节结束标记的校验:第 7 节之后最多 4 个尾部 字节无论内容如何都被接受,而不再要求标准的 "7777"。只应用于已知会输出 非标准尾部的生成器;默认保持严格模式。

type ProbabilityLimit

type ProbabilityLimit struct {
	ScaleFactorRaw uint8
	ScaledValueRaw uint32
	HasValue       bool
}

ProbabilityLimit is one event threshold of a probability template: the sign-magnitude scale factor octet and the 4-octet scaled value, kept raw for the same reason as Level's raw fields — the parameter concepts condition on the exact (scaleFactor, scaledValue) key pair ("at least 1 mm" is (0,1), and a (−1,10) encoding of the same value must not match that entry). Missing sentinels follow the Level convention: 0xFF / 0xFFFFFFFF, with HasValue false.

type Product

type Product struct {
	// Edition is the message's GRIB edition (1 or 2). It determines the code
	// space of every code below: GRIB1 parameter codes come from table 2,
	// level type codes from table 3, and the generating-process id is a
	// centre-defined code; the GRIB2 counterparts come from tables 4.2 /
	// 4.5 / 4.3. Equal numbers do not imply equal meaning.
	Edition           int
	TemplateNumber    int
	ParameterCategory int // octet 10, table 4.1
	ParameterNumber   int // octet 11, table 4.2 (resolved per the discipline)
	// ParameterName is ecCodes' "parameterName": the title of the table 4.2 row
	// for (discipline, category, number) **in the table version this message
	// declares** (section 1 octets 10/11, plus the originating centre for the
	// local tables) — not the newest WMO table. When the declared version has
	// no such table, or the table has no such code, ecCodes renders the bare
	// decimal code ("224", "13", "0"); ParameterName does the same, so it is
	// never empty for a parsed GRIB2 parameter. See spec.ParameterNameFor and
	// spec.ParameterName (the version-independent, always-newest variant).
	//
	// On GRIB1 it stays whatever grib1's table 2 registration produced (empty
	// until RegisterTable2 registers that centre/version).
	ParameterName           string
	TypeOfGeneratingProcess int           // first TableRef=4.3 field (octet 12 in template 4.0)
	ForecastTime            *ForecastTime // nil = the template has no time-unit field
	// EndOfOverallInterval is the "time of end of overall time interval"
	// block carried by the WMO statistical product templates (4.8-4.14). nil
	// when the template has no such field, when the field sits at a
	// parametrized position (see spec.EndIntervalParametrized), when the
	// bytes are truncated or name an impossible date, and always on GRIB1.
	//
	// It is what turns ForecastTime (the interval *start*) into an interval
	// *end* — the anchor for ecCodes' "step" and "validityDate". On the WMO
	// statistical templates the 4.4 forecast-time field marks the beginning
	// of the overall interval, not the end, so a parser that reads only
	// ForecastTime reports step=0 and a validity time one full interval too
	// early on every accumulated / averaged product (tp 6h, mx2t 24h, …).
	//
	// On GRIB1 the equivalent range lives in the section-1 P1/P2 pair under
	// table 5 time-range semantics; Message.StepRange decodes it, this field
	// stays nil there on purpose (different code space, see Edition).
	EndOfOverallInterval *time.Time
	// TypeOfStatisticalProcessing is the table 4.7 code of the outermost
	// time range of the WMO statistical templates (4.8-4.14: 0 = average,
	// 1 = accumulation, 2 = maximum, …). -1 when the template has no such
	// field at a fixed position (instantaneous templates, and the few whose
	// field sits at a parametrized position). The parameter concepts'
	// shortName entries for accumulated / averaged fields condition on this
	// value, so without it "6h accumulation of total precipitation" cannot
	// be told apart from instantaneous specific humidity sharing the same
	// (discipline, category, number).
	TypeOfStatisticalProcessing int
	Level1, Level2              *Level // first/second TableRef=4.5 field; nil = absent
	// ProbabilityType is the table 4.9 code of the probability templates
	// (4.5/4.9 and derivatives, including the NT-parametrized 4.112/4.123:
	// 0 = probability of event below lower limit, 1 = above upper limit,
	// 3 = within intervals, …). -1 when the template has no probability
	// fields or the section is too short to hold them. The event thresholds
	// follow it — see ProbabilityLower / ProbabilityUpper.
	ProbabilityType  int
	ProbabilityLower *ProbabilityLimit // 事件下限;nil = 模板无概率字段
	ProbabilityUpper *ProbabilityLimit // 事件上限;nil = 同上
	// Chemical is non-nil only for the chemistry/aerosol templates; it keeps
	// the table 4.230/4.233 constituent, table 4.238 source/sink process and
	// the size/wavelength intervals the parameter concepts condition on.
	Chemical *Chemical
	NV       int // section 4 octets 6-7: number of coordinate values
}

Product is the parsed section 4. The common core fields are extracted by absolute octet position and table-reference lookup, so they work across product templates without template-specific code. For a local or unknown template only TemplateNumber and NV are filled; the remaining fields stay zero-valued / nil.

type ScaledField

type ScaledField struct {
	Value int
	Valid bool
}

ScaledField is one GRIB2 sign-magnitude field (a `signed[1]` scale factor or a `signed[4]` scaled value) from the chemistry/aerosol product templates. Valid is false when the field holds the all-ones missing sentinel or the section is truncated.

type Section

type Section struct {
	Number int    // octet 5 (standard 0-7; 8 = end marker "7777", never exposed here) // 第 8 八位组(标准 0-7;8 = 结束标记 "7777",从不对外暴露)/ octet 5 (standard 0-7; 8 = end marker "7777", never exposed here)
	Length int    // sections 1+: octets 1-4; section 0: message total length (octets 9-16) // 第 1-4 八位组;第 0 节:消息总长度(第 9-16 八位组)/ sections 1+: octets 1-4; section 0: message total length (octets 9-16)
	Data   []byte // full section bytes starting at octet 1; sections 1+: Data[5:] = content from octet 6 // 自第 1 八位组起的完整节字节;第 1 节起:Data[5:] = 自第 6 八位组起的内容 / full section bytes starting at octet 1; sections 1+: Data[5:] = content from octet 6
}

Section 表示一个 GRIB2 节。对第 1-7 节,Data[0:4] 是 4 八位组的节长度, Data[4] 是节号,Data[5:] 是模板内容(自第 6 八位组起)。第 0 节是固定的 16 字节头部,既无长度前缀也无节号字节("GRIB" + 保留位 + 学科代码 + 版本号 + 8 八位组的消息总长度);对它而言 Length 是消息总长度,Data 是这 16 字节 头部。第 8 节是 4 八位组的结束标记 "7777"(ecCodes section.8.def: `ascii[4] '7777'`);它不是本地使用段——GRIB2 中唯一的本地使用段是第 2 节 (ecCodes sections.def)。WMO 模板 CSV 中的字段位置是节内的绝对八位组编号, 因此"第 N 八位组"的字段位于 Data[N-1]。

Section is one GRIB2 section. For sections 1-7, Data[0:4] holds the 4-octet length, Data[4] the section number, and Data[5:] the template content (from octet 6). Section 0 is the fixed 16-byte header with no length prefix and no number byte ("GRIB" + reserved + discipline + edition + 8-octet message total length); for it Length is the message total length and Data is that 16-byte header. Section 8 is the 4-octet end marker "7777" (ecCodes section.8.def: `ascii[4] '7777'`); it is not a local-use section — the only local-use section in GRIB2 is section 2 (ecCodes sections.def). Field positions in the WMO template CSVs are absolute octet numbers within the section, so a field at "octet N" lives at Data[N-1].

type SectionRef

type SectionRef struct {
	Number int   // section number octet // 节号八位组 / section number octet
	Off    int64 // absolute file offset of the section's first octet // 该节第一个八位组的文件绝对偏移 / absolute file offset of the section's first octet
	Length int   // full section length (octets 1-4) // 完整节长度(第 1-4 八位组)/ full section length (octets 1-4)
}

SectionRef 是文件中某个节的位置(仅头部;正文未读取)。供多要素信封索引 使用。

SectionRef is the location of one section in the file (header only; the body is not read). Used by the multi-field envelope index.

type WebPInfo added in v0.0.4

type WebPInfo struct {
	// Width / Height:画布像素尺寸 / canvas size in pixels
	Width, Height int
	// Lossless:true = VP8L 无损码流,false = VP8 有损 / true for a VP8L lossless bitstream, false for lossy VP8
	Lossless bool
	// Animated:true = 动画 WebP(画布尺寸来自容器) / true for an animated WebP (the canvas size comes from the container)
	Animated bool
}

WebPInfo 描述 local-use 模板 5.49152 消息携带的 WebP 图像。它只读容器头, 不解码像素。

WebPInfo describes the WebP image carried by a local-use template 5.49152 message. It reads the container header only and decodes no pixels.

Directories

Path Synopsis
bench
p7_decode_bench command
cmd
gribdump command
命令 gribdump 是 GRIB2/GRIB1 文件的检视工具:默认打印消息元数据, 并支持 -values N(前 N 个数据值)、-section n(逐字段 Walk 转储,带表名, 可重复)、-json(机器可读输出)以及 -webp(导出模板 5.49152 的 WebP 图像 载荷)。
命令 gribdump 是 GRIB2/GRIB1 文件的检视工具:默认打印消息元数据, 并支持 -values N(前 N 个数据值)、-section n(逐字段 Walk 转储,带表名, 可重复)、-json(机器可读输出)以及 -webp(导出模板 5.49152 的 WebP 图像 载荷)。
paramgen command
命令 paramgen 从 paramdata/(vendored、版本钉死的 ecCodes definitions 子集) 生成 paramdb 包的概念表 Go 数据。
命令 paramgen 从 paramdata/(vendored、版本钉死的 ecCodes definitions 子集) 生成 paramdb 包的概念表 Go 数据。
specgen command
命令 specgen 从 specdata/ 里内置的 WMO CSV 文件生成 simple-grib 的 Go 规范数据。
命令 specgen 从 specdata/ 里内置的 WMO CSV 文件生成 simple-grib 的 Go 规范数据。
Package grib1 is a pure-Go reader for WMO GRIB edition 1 (FM 92-IX) messages.
Package grib1 is a pure-Go reader for WMO GRIB edition 1 (FM 92-IX) messages.
Package gribw encodes GRIB2 messages.
Package gribw encodes GRIB2 messages.
gribw1 是 GRIB edition 1 的**写入**器(grib1 包的逆操作、gribw 包的兄弟)。
gribw1 是 GRIB edition 1 的**写入**器(grib1 包的逆操作、gribw 包的兄弟)。
Package grid 实现 GRIB2 第 3 节(网格定义)模板:解码模板字段并计算 每个网格点的地理坐标。
Package grid 实现 GRIB2 第 3 节(网格定义)模板:解码模板字段并计算 每个网格点的地理坐标。
internal
octetio
Package octetio 提供大端、带边界检查的字节切片读取,外加为 GRIB2 位图准备的 MSB-first 比特访问。
Package octetio 提供大端、带边界检查的字节切片读取,外加为 GRIB2 位图准备的 MSB-first 比特访问。
Package pack 处理 GRIB2 第 5 段(数据表示模板):数值模板解包为 float32 网格点值;local-use 的 5.49152 是 WebP 图像载荷,拒绝数值解码。
Package pack 处理 GRIB2 第 5 段(数据表示模板):数值模板解包为 float32 网格点值;local-use 的 5.49152 是 WebP 图像载荷,拒绝数值解码。
Package paramdb 回答 ecCodes 用 "concept" 机制回答的参数问题: shortName、name、paramId、units 与 typeOfLevel。
Package paramdb 回答 ecCodes 用 "concept" 机制回答的参数问题: shortName、name、paramId、units 与 typeOfLevel。
Package spec 提供 WMO GRIB2 规范数据的只读访问:代码表(表 4.1 参数类别、 表 4.2.<discipline>.<category> 参数、CCT-11 中心等)与模板字段描述符由 cmd/specgen 从 specdata/ 源数据生成;包内提供按表 id 查表、按代码区间匹配 以及参数三元组命名的接口。
Package spec 提供 WMO GRIB2 规范数据的只读访问:代码表(表 4.1 参数类别、 表 4.2.<discipline>.<category> 参数、CCT-11 中心等)与模板字段描述符由 cmd/specgen 从 specdata/ 源数据生成;包内提供按表 id 查表、按代码区间匹配 以及参数三元组命名的接口。
这个目录是 simple-grib 的 WebAssembly 入口。
这个目录是 simple-grib 的 WebAssembly 入口。
tools/mkstandalone command
mkstandalone 把 wasm/viewer.html 打成"双击就能用"的单文件版本: 内联 wasm_exec.js,并把 grib.wasm 用 gzip + base64 塞进页面。
mkstandalone 把 wasm/viewer.html 打成"双击就能用"的单文件版本: 内联 wasm_exec.js,并把 grib.wasm 用 gzip + base64 塞进页面。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL