forked from gsn/predictor
55 lines
1,011 B
Go
55 lines
1,011 B
Go
package grib
|
||
|
||
import (
|
||
"encoding/binary"
|
||
"math"
|
||
"os"
|
||
|
||
mmap "github.com/edsrzf/mmap-go"
|
||
)
|
||
|
||
type cube struct {
|
||
mm mmap.MMap // read‑only, U followed by V (float32 LE)
|
||
t, p, lat, lon int
|
||
bytesPerVar int64
|
||
file *os.File
|
||
}
|
||
|
||
func openCube(path string) (*cube, error) {
|
||
f, err := os.Open(path)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
mm, err := mmap.Map(f, mmap.RDONLY, 0)
|
||
if err != nil {
|
||
f.Close()
|
||
return nil, err
|
||
}
|
||
|
||
const (
|
||
nT = 17
|
||
nP = 34
|
||
nLat = 361
|
||
nLon = 720
|
||
)
|
||
|
||
return &cube{mm: mm, t: nT, p: nP, lat: nLat, lon: nLon, bytesPerVar: int64(nT * nP * nLat * nLon * 4), file: f}, nil
|
||
}
|
||
|
||
func (c *cube) val(varIdx, ti, pi, y, x int) float32 {
|
||
idx := (((ti*c.p+pi)*c.lat + y) * c.lon) + x
|
||
off := int64(varIdx)*c.bytesPerVar + int64(idx)*4
|
||
bits := binary.LittleEndian.Uint32(c.mm[off : off+4])
|
||
return math.Float32frombits(bits)
|
||
}
|
||
|
||
func (c *cube) Close() error {
|
||
if c.mm != nil {
|
||
c.mm.Unmap()
|
||
}
|
||
if c.file != nil {
|
||
return c.file.Close()
|
||
}
|
||
return nil
|
||
}
|