├── cmd └── examples │ ├── file-grib2csv │ ├── gfs.t00z.pgrb2.0p25.f001 │ └── main.go │ └── http-grib2csv │ └── main.go ├── internal ├── ncx.c.go ├── CodeTable4_4.h.go ├── ieee2flt.c.go ├── ieee2flt_nan.c.go ├── wgrib2.c.go ├── bitstream.c.go ├── addtime.c.go ├── Earth.c.go ├── missing.c.go ├── Latlon.c.go ├── int8.c.go ├── cname.c.go ├── Code_Values.c.go ├── unpk.c.go ├── VerfTime.c.go ├── stagger.c.go ├── stubs.go ├── CodeTable.c.go ├── FlagTable.c.go ├── unpk_0.c.go ├── grib2.c.go ├── Sec3.c.go ├── Level.c.go └── geo.c.go ├── vendor └── github.com │ └── pkg │ └── errors │ ├── .travis.yml │ ├── .gitignore │ ├── appveyor.yml │ ├── bench_test.go │ ├── LICENSE │ ├── README.md │ ├── stack.go │ ├── errors_test.go │ ├── example_test.go │ ├── stack_test.go │ ├── errors.go │ └── format_test.go ├── .gitignore ├── .vscode ├── settings.json ├── tasks.json └── launch.json ├── Gopkg.toml ├── LICENSE ├── reader.go └── README.md /cmd/examples/file-grib2csv/gfs.t00z.pgrb2.0p25.f001: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/amsokol/go-grib2/HEAD/cmd/examples/file-grib2csv/gfs.t00z.pgrb2.0p25.f001 -------------------------------------------------------------------------------- /internal/ncx.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // #define X_INT_MAX 2147483647 4 | const X_INT_MAX = 2147483647 5 | 6 | // #define INT_MAX X_INT_MAX 7 | const INT_MAX = X_INT_MAX 8 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: github.com/pkg/errors 3 | go: 4 | - 1.4.3 5 | - 1.5.4 6 | - 1.6.2 7 | - 1.7.1 8 | - tip 9 | 10 | script: 11 | - go test -v ./... 12 | -------------------------------------------------------------------------------- /internal/CodeTable4_4.h.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | const ( 4 | MINUTE = 0 5 | HOUR = 1 6 | DAY = 2 7 | MONTH = 3 8 | YEAR = 4 9 | DECADE = 5 10 | NORMAL = 6 11 | CENTURY = 7 12 | HOUR3 = 10 13 | HOUR6 = 11 14 | HOUR12 = 12 15 | SECOND = 13 16 | ) 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | .idea 16 | .vscode -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "cSpell.words": [ 4 | "wgrib", 5 | "amsokol", 6 | "verftime", 7 | "Verf", 8 | "grib", 9 | "dtime", 10 | "mtab", 11 | "infile", 12 | "pgrb", 13 | "gribs", 14 | "Wrapf", 15 | "dlen", 16 | "golang" 17 | ], 18 | "go.buildOnSave": "package" 19 | } 20 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "taskName": "build", 8 | "type": "shell", 9 | "command": "go build .", 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | } 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "debug", 9 | "remotePath": "", 10 | "port": 2345, 11 | "host": "127.0.0.1", 12 | "program": "${fileDirname}", 13 | "env": {}, 14 | "args": [], 15 | "showLog": true 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /Gopkg.toml: -------------------------------------------------------------------------------- 1 | 2 | # Gopkg.toml example 3 | # 4 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md 5 | # for detailed Gopkg.toml documentation. 6 | # 7 | # required = ["github.com/user/thing/cmd/thing"] 8 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] 9 | # 10 | # [[constraint]] 11 | # name = "github.com/user/project" 12 | # version = "1.0.0" 13 | # 14 | # [[constraint]] 15 | # name = "github.com/user/project2" 16 | # branch = "dev" 17 | # source = "github.com/myfork/project2" 18 | # 19 | # [[override]] 20 | # name = "github.com/x/y" 21 | # version = "2.4.0" 22 | 23 | 24 | [[constraint]] 25 | name = "github.com/pkg/errors" 26 | version = "0.8.0" 27 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: build-{build}.{branch} 2 | 3 | clone_folder: C:\gopath\src\github.com\pkg\errors 4 | shallow_clone: true # for startup speed 5 | 6 | environment: 7 | GOPATH: C:\gopath 8 | 9 | platform: 10 | - x64 11 | 12 | # http://www.appveyor.com/docs/installed-software 13 | install: 14 | # some helpful output for debugging builds 15 | - go version 16 | - go env 17 | # pre-installed MinGW at C:\MinGW is 32bit only 18 | # but MSYS2 at C:\msys64 has mingw64 19 | - set PATH=C:\msys64\mingw64\bin;%PATH% 20 | - gcc --version 21 | - g++ --version 22 | 23 | build_script: 24 | - go install -v ./... 25 | 26 | test_script: 27 | - set PATH=C:\gopath\bin;%PATH% 28 | - go test -v ./... 29 | 30 | #artifacts: 31 | # - path: '%GOPATH%\bin\*.exe' 32 | deploy: off 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Aleksandr Sokolovskii 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/bench_test.go: -------------------------------------------------------------------------------- 1 | // +build go1.7 2 | 3 | package errors 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | 9 | stderrors "errors" 10 | ) 11 | 12 | func noErrors(at, depth int) error { 13 | if at >= depth { 14 | return stderrors.New("no error") 15 | } 16 | return noErrors(at+1, depth) 17 | } 18 | func yesErrors(at, depth int) error { 19 | if at >= depth { 20 | return New("ye error") 21 | } 22 | return yesErrors(at+1, depth) 23 | } 24 | 25 | func BenchmarkErrors(b *testing.B) { 26 | var toperr error 27 | type run struct { 28 | stack int 29 | std bool 30 | } 31 | runs := []run{ 32 | {10, false}, 33 | {10, true}, 34 | {100, false}, 35 | {100, true}, 36 | {1000, false}, 37 | {1000, true}, 38 | } 39 | for _, r := range runs { 40 | part := "pkg/errors" 41 | if r.std { 42 | part = "errors" 43 | } 44 | name := fmt.Sprintf("%s-stack-%d", part, r.stack) 45 | b.Run(name, func(b *testing.B) { 46 | var err error 47 | f := yesErrors 48 | if r.std { 49 | f = noErrors 50 | } 51 | b.ReportAllocs() 52 | for i := 0; i < b.N; i++ { 53 | err = f(0, r.stack) 54 | } 55 | b.StopTimer() 56 | toperr = err 57 | }) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /internal/ieee2flt.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* wesley ebisuzaki v0.2 4 | * 5 | * takes 4 byte character string (single precision ieee big-endian) 6 | * and returns a float 7 | * 8 | * doesn't handle NAN, infinity and any other funny stuff in ieee 9 | * 10 | * ansi C 11 | */ 12 | /* 13 | float ieee2flt(unsigned char *ieee) { 14 | double fmant; 15 | int exp; 16 | 17 | if ((ieee[0] & 127) == 0 && ieee[1] == 0 && ieee[2] == 0 && ieee[3] == 0) 18 | return (float) 0.0; 19 | 20 | exp = ((ieee[0] & 127) << 1) + (ieee[1] >> 7); 21 | fmant = (double) ((int) ieee[3] + (int) (ieee[2] << 8) + 22 | (int) ((ieee[1] | 128) << 16)); 23 | if (ieee[0] & 128) fmant = -fmant; 24 | return (float) (ldexp(fmant, (int) (exp - 128 - 22))); 25 | } 26 | */ 27 | 28 | func ieee2flt(ieee []unsigned_char) float { 29 | var fmant double 30 | var exp int 31 | 32 | if (ieee[0]&127) == 0 && ieee[1] == 0 && ieee[2] == 0 && ieee[3] == 0 { 33 | return float(0.0) 34 | } 35 | 36 | exp = ((int(ieee[0]) & 127) << 1) + (int(ieee[1]) >> 7) 37 | fmant = (double)(int(ieee[3]) + (int(ieee[2]) << 8) + 38 | (int(ieee[1]|128) << 16)) 39 | if (ieee[0] & 128) != 0 { 40 | fmant = -fmant 41 | } 42 | return float(ldexp(fmant, (int)(exp-128-22))) 43 | } 44 | -------------------------------------------------------------------------------- /internal/ieee2flt_nan.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* wesley ebisuzaki v0.2 4 | * 5 | * takes 4 byte character string (single precision ieee big-endian) 6 | * and returns a float 7 | * 8 | * NaN, infinity are mapped into UNDEFINED. 9 | * 10 | * ansi C 11 | */ 12 | /* 13 | float ieee2flt_nan(unsigned char *ieee) { 14 | double fmant; 15 | int exp; 16 | 17 | if ((ieee[0] & 127) == 0 && ieee[1] == 0 && ieee[2] == 0 && ieee[3] == 0) 18 | return (float) 0.0; 19 | 20 | exp = ((ieee[0] & 127) << 1) + (ieee[1] >> 7); 21 | 22 | if (exp == 255) return (float) UNDEFINED; 23 | 24 | fmant = (double) ((int) ieee[3] + (int) (ieee[2] << 8) + 25 | (int) ((ieee[1] | 128) << 16)); 26 | if (ieee[0] & 128) fmant = -fmant; 27 | 28 | 29 | return (float) (ldexp(fmant, (int) (exp - 128 - 22))); 30 | } 31 | */ 32 | 33 | func ieee2flt_nan(ieee []unsigned_char) float { 34 | var fmant double 35 | var exp int 36 | 37 | if (ieee[0]&127) == 0 && ieee[1] == 0 && ieee[2] == 0 && ieee[3] == 0 { 38 | return float(0.0) 39 | } 40 | 41 | exp = (int(ieee[0]&127) << 1) + (int(ieee[1]) >> 7) 42 | 43 | if exp == 255 { 44 | return float(UNDEFINED) 45 | } 46 | 47 | fmant = double(int(ieee[3]) + (int(ieee[2]) << 8) + 48 | (int(ieee[1]|128) << 16)) 49 | if (ieee[0] & 128) != 0 { 50 | fmant = -fmant 51 | } 52 | 53 | return float(ldexp(fmant, int(exp-128-22))) 54 | } 55 | -------------------------------------------------------------------------------- /internal/wgrib2.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | // enum output_order_type {raw,wesn,wens}; 4 | type output_order_type int 5 | 6 | const ( 7 | raw = 0 8 | wesn = 1 9 | wens = 2 10 | ) 11 | 12 | const ( 13 | UNDEFINED = 9.999e20 14 | UNDEFINED_LOW = 9.9989e20 15 | UNDEFINED_HIGH = 9.9991e20 16 | ) 17 | 18 | // enum output_order_type output_order, output_order_wanted; 19 | var output_order output_order_type = wesn 20 | var output_order_wanted output_order_type = wesn 21 | 22 | // #define DEFINED_VAL(x) ((x) < UNDEFINED_LOW || (x) > UNDEFINED_HIGH) 23 | func DEFINED_VAL(x float) bool { 24 | return (x) < UNDEFINED_LOW || (x) > UNDEFINED_HIGH 25 | } 26 | 27 | type gribtable_s struct { 28 | disc int /* Section 0 Discipline */ 29 | mtab_set int /* Section 1 Master Tables Version Number used by set_var */ 30 | mtab_low int /* Section 1 Master Tables Version Number low range of tables */ 31 | mtab_high int /* Section 1 Master Tables Version Number high range of tables */ 32 | cntr int /* Section 1 originating centre, used for local tables */ 33 | ltab int /* Section 1 Local Tables Version Number */ 34 | pcat int /* Section 4 Template 4.0 Parameter category */ 35 | pnum int /* Section 4 Template 4.0 Parameter number */ 36 | name string 37 | desc string 38 | unit string 39 | } 40 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Dave Cheney 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /cmd/examples/file-grib2csv/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "os" 8 | 9 | "github.com/amsokol/go-grib2" 10 | ) 11 | 12 | func main() { 13 | grib2file := "./gfs.t00z.pgrb2.0p25.f001" 14 | csvfile := "./gfs.t00z.pgrb2.0p25.f001.csv" 15 | 16 | infile, err := os.Open(grib2file) 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | defer infile.Close() 21 | 22 | data, err := ioutil.ReadAll(infile) 23 | if err != nil { 24 | log.Fatal(err) 25 | } 26 | 27 | gribs, err := grib2.Read(data) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | log.Printf("Source package contains %d GRIB2 file(s)\n", len(gribs)) 32 | 33 | outfile, err := os.Create(csvfile) 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | defer outfile.Close() 38 | 39 | for _, g := range gribs { 40 | log.Printf("Published='%s', Forecast='%s', Parameter='%s', Unit='%s', Description='%s'\n", 41 | g.RefTime.Format("2006-01-02 15:04:05"), g.VerfTime.Format("2006-01-02 15:04:05"), g.Name, g.Unit, g.Description) 42 | 43 | refTime := g.RefTime 44 | verfTime := g.VerfTime 45 | name := g.Name 46 | level := g.Level 47 | for _, v := range g.Values { 48 | lon := v.Longitude 49 | if lon > 180.0 { 50 | lon -= 360.0 51 | } 52 | 53 | _, err := fmt.Fprintf(outfile, "\"%s\",\"%s\",\"%s\",\"%s\",%g,%g,%g\n", 54 | refTime.Format("2006-01-02 15:04:05"), 55 | verfTime.Format("2006-01-02 15:04:05"), 56 | name, 57 | level, 58 | lon, 59 | v.Latitude, 60 | v.Value) 61 | if err != nil { 62 | log.Fatalln("error writing record to csv:", err) 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /internal/bitstream.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | var ones = []int{0, 1, 3, 7, 15, 31, 63, 127, 255} 4 | 5 | /* 6 | * void rd_bitstream_flt 7 | * rd_bitstream_flt() is like rd_bitstream() except that returns a float instead of int 8 | */ 9 | func rd_bitstream_flt(p []unsigned_char, offset int, u []float, n_bits int, n int) error { 10 | 11 | var tbits unsigned_int 12 | var i, t_bits, new_t_bits int 13 | 14 | // not the best of tests 15 | 16 | if INT_MAX <= 2147483647 && n_bits > 31 { 17 | return fatal_error_i("rd_bitstream: n_bits is %d", n_bits) 18 | } 19 | 20 | if offset < 0 || offset > 7 { 21 | return fatal_error_i("rd_bitstream_flt: illegal offset %d", offset) 22 | } 23 | 24 | if n_bits == 0 { 25 | for i = 0; i < n; i++ { 26 | u[i] = 0.0 27 | } 28 | return nil 29 | } 30 | 31 | t_bits = 8 - offset 32 | p_index := 0 33 | tbits = unsigned_int(p[p_index]) & unsigned_int(ones[t_bits]) 34 | p_index++ 35 | 36 | for i = 0; i < n; i++ { 37 | 38 | for n_bits-t_bits >= 8 { 39 | t_bits += 8 40 | tbits = (tbits << 8) | unsigned_int(p[p_index]) 41 | p_index++ 42 | } 43 | 44 | if n_bits > t_bits { 45 | new_t_bits = 8 - (n_bits - t_bits) 46 | u[i] = float(int(tbits<> unsigned_int(new_t_bits)))) 47 | t_bits = new_t_bits 48 | tbits = unsigned_int(p[p_index]) & unsigned_int(ones[t_bits]) 49 | p_index++ 50 | } else if n_bits == t_bits { 51 | u[i] = float(tbits) 52 | tbits = 0 53 | t_bits = 0 54 | } else { 55 | t_bits -= n_bits 56 | u[i] = float(tbits >> unsigned_int(t_bits)) 57 | tbits = tbits & unsigned_int(ones[t_bits]) 58 | } 59 | } 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /internal/addtime.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | func get_time(p []unsigned_char, year *int, month *int, day *int, hour *int, minute *int, second *int) { 8 | *year = (int(p[0]) << 8) | int(p[1]) 9 | *month = int(p[2]) 10 | *day = int(p[3]) 11 | *hour = int(p[4]) 12 | *minute = int(p[5]) 13 | *second = int(p[6]) 14 | } 15 | 16 | func add_time(year *int, month *int, day *int, hour *int, minute *int, second *int, dtime int, unit int) { 17 | if dtime == 0 { 18 | return 19 | } 20 | add_dt(year, month, day, hour, minute, second, dtime, unit) 21 | } 22 | 23 | func add_dt(year *int, month *int, day *int, hour *int, minute *int, second *int, dtime int, unit int) { 24 | 25 | if unit == 255 || unit == -1 { 26 | return 27 | } // no valid time unit 28 | if dtime == 0xffffffff { 29 | return 30 | } // missing dtime 31 | 32 | t := time.Date(*year, time.Month(*month), *day, *hour, *minute, *second, 0, time.UTC) 33 | 34 | switch unit { 35 | case YEAR: 36 | t = t.AddDate(dtime, 0, 0) 37 | case DECADE: 38 | t = t.AddDate(10*dtime, 0, 0) 39 | case CENTURY: 40 | t = t.AddDate(100*dtime, 0, 0) 41 | case NORMAL: 42 | t = t.AddDate(30*dtime, 0, 0) 43 | case MONTH: 44 | t = t.AddDate(0, dtime, 0) 45 | case DAY: 46 | t = t.AddDate(0, 0, dtime) 47 | case HOUR12: 48 | t = t.Add(time.Duration(dtime) * time.Hour * 12) 49 | case HOUR6: 50 | t = t.Add(time.Duration(dtime) * time.Hour * 6) 51 | case HOUR3: 52 | t = t.Add(time.Duration(dtime) * time.Hour * 3) 53 | case HOUR: 54 | t = t.Add(time.Duration(dtime) * time.Hour) 55 | case MINUTE: 56 | t = t.Add(time.Duration(dtime) * time.Minute) 57 | case SECOND: 58 | t = t.Add(time.Duration(dtime) * time.Second) 59 | } 60 | *year = t.Year() 61 | *month = int(t.Month()) 62 | *day = t.Day() 63 | *hour = t.Hour() 64 | *minute = t.Minute() 65 | *second = t.Second() 66 | } 67 | -------------------------------------------------------------------------------- /cmd/examples/http-grib2csv/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | "os" 9 | 10 | "github.com/amsokol/go-grib2" 11 | ) 12 | 13 | func main() { 14 | log.Println("Downloading data from HTTP server...") 15 | res, err := http.Get("http://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25_1hr.pl?file=gfs.t00z.pgrb2.0p25.f001&lev_10_m_above_ground=on&var_UGRD=on&var_VGRD=on&subregion=&leftlon=-10&rightlon=19&toplat=60&bottomlat=35.7&dir=%2Fgfs.2017072000") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | log.Println("Data downloaded") 20 | 21 | csvfile := "./gfs.t00z.pgrb2.0p25.f001.csv" 22 | 23 | data, err := ioutil.ReadAll(res.Body) 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | res.Body.Close() 28 | 29 | gribs, err := grib2.Read(data) 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | log.Printf("Source package contains %d GRIB2 file(s)\n", len(gribs)) 34 | 35 | outfile, err := os.Create(csvfile) 36 | if err != nil { 37 | log.Fatal(err) 38 | } 39 | defer outfile.Close() 40 | 41 | for _, g := range gribs { 42 | log.Printf("Published='%s', Forecast='%s', Parameter='%s', Unit='%s', Description='%s'\n", 43 | g.RefTime.Format("2006-01-02 15:04:05"), g.VerfTime.Format("2006-01-02 15:04:05"), g.Name, g.Unit, g.Description) 44 | 45 | refTime := g.RefTime 46 | verfTime := g.VerfTime 47 | name := g.Name 48 | level := g.Level 49 | for _, v := range g.Values { 50 | lon := v.Longitude 51 | if lon > 180.0 { 52 | lon -= 360.0 53 | } 54 | 55 | _, err := fmt.Fprintf(outfile, "\"%s\",\"%s\",\"%s\",\"%s\",%g,%g,%g\n", 56 | refTime.Format("2006-01-02 15:04:05"), 57 | verfTime.Format("2006-01-02 15:04:05"), 58 | name, 59 | level, 60 | lon, 61 | v.Latitude, 62 | v.Value) 63 | if err != nil { 64 | log.Fatalln("error writing record to csv:", err) 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /internal/Earth.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* function to return the size of the earth */ 4 | 5 | func radius_earth(sec [][]unsigned_char) (double, error) { 6 | var table_3_2 int 7 | var radius double 8 | var p []unsigned_char 9 | var factor, value int 10 | 11 | p = code_table_3_2_location(sec) 12 | if p == nil { 13 | return 0, fatal_error("radius_earth: code_table 3.2 is unknown", "") 14 | } 15 | 16 | table_3_2 = int(p[0]) 17 | 18 | /* set a default value .. not sure what to do with most values */ 19 | radius = 6367.47 * 1000.0 20 | if table_3_2 == 0 { 21 | radius = 6367.47 * 1000.0 22 | } else if table_3_2 == 1 { 23 | factor = INT1(p[1]) 24 | value = int4(p[2:]) 25 | radius = scaled2dbl(factor, value) 26 | if radius < 6300000.0 || radius > 6400000.0 { 27 | return 0, fatal_error_i("radius of earth is %d m", int(radius)) 28 | } 29 | } else if table_3_2 == 2 { 30 | radius = (6378.160 + 6356.775) * 0.5 * 1000.0 31 | } else if table_3_2 == 3 || table_3_2 == 7 { 32 | /* get major axis */ 33 | factor = INT1(p[6]) 34 | value = int4(p[7:]) 35 | radius = scaled2dbl(factor, value) 36 | /* get minor axis */ 37 | factor = INT1(p[11]) 38 | value = int4(p[12:]) 39 | radius = (radius + scaled2dbl(factor, value)) * 0.5 40 | 41 | /* radius in km, convert to m */ 42 | if table_3_2 == 3 { 43 | radius *= 1000.0 44 | } 45 | 46 | if radius < 6300000.0 || radius > 6400000.0 { 47 | return 0, fatal_error_i("radius of earth is %d m", int(radius)) 48 | } 49 | } else if table_3_2 == 4 { 50 | radius = (6378.137 + 6356.752) * 0.5 * 1000.0 51 | } else if table_3_2 == 5 { 52 | radius = (6378.137 + 6356.752) * 0.5 * 1000.0 53 | } else if table_3_2 == 6 { 54 | radius = 6371.2290 * 1000.0 55 | } else if table_3_2 == 8 { 56 | radius = 6371.200 * 1000.0 57 | } else if table_3_2 == 9 { 58 | radius = (6377563.396 + 6356256.909) * 0.5 59 | } 60 | 61 | return radius, nil 62 | } 63 | -------------------------------------------------------------------------------- /internal/missing.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | * Public domain: w. ebisuzaki 5 | * number of missing data points as determined by bitmap 6 | * 7 | * v1.1: just faster my dear 8 | * v1.2: just faster my dear 9 | * v1.3: just faster my dear 10 | * 11 | */ 12 | 13 | var bitsum = []int{ 14 | 8, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4, 15 | 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 16 | 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 17 | 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 18 | 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 19 | 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 20 | 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 21 | 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 22 | 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 23 | 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 24 | 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 25 | 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 26 | 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 27 | 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 28 | 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 29 | 4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0} 30 | 31 | func missing_points(bitmap []unsigned_char, n unsigned_int) unsigned_int { 32 | 33 | var count, i, j, rem unsigned_int 34 | if bitmap == nil { 35 | return 0 36 | } 37 | /* 38 | count = 0; 39 | while (n >= 8) { 40 | tmp = *bitmap++; 41 | n -= 8; 42 | count += bitsum[tmp]; 43 | } 44 | tmp = *bitmap | ((1 << (8 - n)) - 1); 45 | count += bitsum[tmp]; 46 | */ 47 | 48 | j = n >> 3 49 | rem = n & 7 50 | count = 0 51 | //#pragma omp parallel for private(i) reduction(+:count) 52 | for i = 0; i < j; i++ { 53 | count += unsigned_int(bitsum[bitmap[i]]) 54 | } 55 | //count += rem ? bitsum[bitmap[j] | ((1 << (8 - rem)) - 1)] : 0; 56 | if rem != 0 { 57 | count += unsigned_int(bitsum[bitmap[j]|((1<<(8-rem))-1)]) 58 | } 59 | 60 | return count 61 | } 62 | -------------------------------------------------------------------------------- /internal/Latlon.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | int get_latlon(unsigned char **sec, double **lon, double **lat) { 5 | 6 | int grid_template; 7 | 8 | if (*lat != NULL) { 9 | free(*lat); 10 | free(*lon); 11 | *lat = *lon = NULL; 12 | } 13 | 14 | grid_template = code_table_3_1(sec); 15 | if (grid_template == 0) { 16 | regular2ll(sec, lat, lon); 17 | } 18 | else if (grid_template == 1) { // rotated lat-lon 19 | rot_regular2ll(sec, lat, lon); 20 | } 21 | else if (grid_template == 10) { 22 | mercator2ll(sec, lat, lon); 23 | } 24 | else if (grid_template == 20) { 25 | polar2ll(sec, lat, lon); 26 | } 27 | else if (grid_template == 30) { 28 | lambert2ll(sec, lat, lon); 29 | } 30 | else if (grid_template == 40) { 31 | gauss2ll(sec, lat, lon); 32 | } 33 | else if (grid_template == 90) { 34 | space_view2ll(sec, lat, lon); 35 | } 36 | else if (grid_template == 130) { 37 | irr_grid2ll(sec, lat, lon); 38 | } 39 | 40 | return 0; 41 | } 42 | */ 43 | func get_latlon(sec [][]unsigned_char, lon *[]double, lat *[]double) error { 44 | 45 | var grid_template int 46 | 47 | grid_template = code_table_3_1(sec) 48 | if grid_template == 0 { 49 | return regular2ll(sec, lat, lon) 50 | } else if grid_template == 1 { // rotated lat-lon 51 | return rot_regular2ll(sec, lat, lon) 52 | } else if grid_template == 10 { 53 | return mercator2ll(sec, lat, lon) 54 | } else if grid_template == 20 { 55 | return polar2ll(sec, lat, lon) 56 | } else if grid_template == 30 { 57 | return lambert2ll(sec, lat, lon) 58 | } else if grid_template == 40 { 59 | // TODO: port gauss2ll 60 | // gauss2ll(sec, lat, lon) 61 | } else if grid_template == 90 { 62 | // TODO: port space_view2ll 63 | // space_view2ll(sec, lat, lon) 64 | } else if grid_template == 130 { 65 | // TODO: port irr_grid2ll 66 | // irr_grid2ll(sec, lat, lon) 67 | } 68 | 69 | return fatal_error("Unsupported Grid template: %d", grid_template) 70 | } 71 | -------------------------------------------------------------------------------- /internal/int8.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | * uint4_missing 5 | * if missing return 0 6 | * uint4_missing is only used in Sec3.c where an undefined nx/ny == 0 is a good responce 7 | */ 8 | /* 9 | unsigned int uint4_missing(unsigned const char *p) { 10 | int t; 11 | 12 | t = p[0]; 13 | t = t << 8 | p[1]; 14 | t = t << 8 | p[2]; 15 | t = t << 8 | p[3]; 16 | 17 | if (t == 0xffffffff) return 0; 18 | return t; 19 | } 20 | */ 21 | func uint4_missing(p []unsigned_char) unsigned_int { 22 | var t int 23 | 24 | t = int(p[0]) 25 | t = t<<8 | int(p[1]) 26 | t = t<<8 | int(p[2]) 27 | t = t<<8 | int(p[3]) 28 | 29 | if t == 0xffffffff { 30 | return 0 31 | } 32 | return unsigned_int(t) 33 | } 34 | 35 | /* 36 | int int2(unsigned const char *p) { 37 | int i; 38 | if (p[0] & 0x80) { 39 | i = -(((p[0] & 0x7f) << 8) + p[1]); 40 | } 41 | else { 42 | i = (p[0] << 8) + p[1]; 43 | } 44 | return i; 45 | } 46 | */ 47 | func int2(p []unsigned_char) int { 48 | var i int 49 | if (p[0] & 0x80) != 0 { 50 | i = -(((int(p[0]) & 0x7f) << 8) + int(p[1])) 51 | } else { 52 | i = (int(p[0]) << 8) + int(p[1]) 53 | } 54 | return i 55 | } 56 | 57 | /* 58 | unsigned int uint2(unsigned char const *p) { 59 | return (p[0] << 8) + p[1]; 60 | } 61 | */ 62 | func uint2(p []unsigned_char) unsigned_int { 63 | return (unsigned_int(p[0]) << 8) + unsigned_int(p[1]) 64 | } 65 | 66 | // 67 | // floating point values are often represented as int * power of 10 68 | // 69 | func scaled2flt(scale_factor int, scale_value int) float { 70 | if scale_factor == 0 { 71 | return float(scale_value) 72 | } 73 | if scale_factor < 0 { 74 | return float(double(scale_value) * Int_Power(10.0, -scale_factor)) 75 | } 76 | return float(double(scale_value) / Int_Power(10.0, scale_factor)) 77 | } 78 | 79 | func scaled2dbl(scale_factor int, scale_value int) double { 80 | if scale_factor == 0 { 81 | return double(scale_value) 82 | } 83 | if scale_factor < 0 { 84 | return double(scale_value) * Int_Power(10.0, -scale_factor) 85 | } 86 | return double(scale_value) / Int_Power(10.0, scale_factor) 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/README.md: -------------------------------------------------------------------------------- 1 | # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) 2 | 3 | Package errors provides simple error handling primitives. 4 | 5 | `go get github.com/pkg/errors` 6 | 7 | The traditional error handling idiom in Go is roughly akin to 8 | ```go 9 | if err != nil { 10 | return err 11 | } 12 | ``` 13 | which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. 14 | 15 | ## Adding context to an error 16 | 17 | The errors.Wrap function returns a new error that adds context to the original error. For example 18 | ```go 19 | _, err := ioutil.ReadAll(r) 20 | if err != nil { 21 | return errors.Wrap(err, "read failed") 22 | } 23 | ``` 24 | ## Retrieving the cause of an error 25 | 26 | Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. 27 | ```go 28 | type causer interface { 29 | Cause() error 30 | } 31 | ``` 32 | `errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: 33 | ```go 34 | switch err := errors.Cause(err).(type) { 35 | case *MyError: 36 | // handle specifically 37 | default: 38 | // unknown error 39 | } 40 | ``` 41 | 42 | [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). 43 | 44 | ## Contributing 45 | 46 | We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. 47 | 48 | Before proposing a change, please discuss your change by raising an issue. 49 | 50 | ## Licence 51 | 52 | BSD-2-Clause 53 | -------------------------------------------------------------------------------- /internal/cname.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | * get the name information 5 | * 6 | * if inv_out, name, desc, unit == NULL, not used 7 | * 8 | * v1.0 Wesley Ebisuzaki 2006 9 | * v1.1 Wesley Ebisuzaki 4/2007 netcdf support 10 | * v1.2 Wesley Ebisuzaki 4/2007 multiple table support 11 | * v1.3 Wesley Ebisuzaki 6/2011 make parameter cat >= 192 local 12 | * v1.4 Wesley Ebisuzaki 2/2012 fixed search_gribtab for local tables 13 | * v1.5 Wesley Ebisuzaki 4/2013 gribtab -> gribtable, added user_gribtable 14 | */ 15 | func getName(sec [][]unsigned_char, name *string, desc *string, unit *string) error { 16 | 17 | var discipline /*center, mastertab, localtab,*/, parmcat, parmnum int 18 | var pdt int 19 | var p *gribtable_s 20 | var p_unit string 21 | 22 | /* 23 | if user_gribtable != nil { 24 | p = search_gribtable(user_gribtable, sec) 25 | } 26 | */ 27 | 28 | p, err := search_gribtable(gribtable, sec) 29 | if err != nil { 30 | return fatal_error_wrap(err, "Failed to execute search_gribtable") 31 | } 32 | 33 | p_unit = "unit" 34 | if p != nil { 35 | p_unit = p.unit 36 | pdt = code_table_4_0(sec) 37 | if pdt == 5 || pdt == 9 { 38 | p_unit = "prob" 39 | } 40 | } 41 | 42 | if p != nil { 43 | *name = p.name 44 | *desc = p.desc 45 | *unit = p_unit 46 | } else { 47 | discipline = GB2_Discipline(sec) 48 | // center = GB2_Center(sec) 49 | // mastertab = GB2_MasterTable(sec) 50 | // localtab = GB2_LocalTable(sec) 51 | parmcat = GB2_ParmCat(sec) 52 | parmnum = GB2_ParmNum(sec) 53 | 54 | *name = sprintf("var%d_%d_%d", discipline, parmcat, parmnum) 55 | *desc = "desc" 56 | *unit = p_unit 57 | } 58 | return nil 59 | } 60 | 61 | func search_gribtable(gts []gribtable_s, sec [][]unsigned_char) (*gribtable_s, error) { 62 | var discipline, center, mastertab, localtab, parmcat, parmnum int 63 | var use_local_table bool 64 | // static int count = 0; 65 | 66 | discipline = GB2_Discipline(sec) 67 | center = GB2_Center(sec) 68 | mastertab = GB2_MasterTable(sec) 69 | localtab = GB2_LocalTable(sec) 70 | parmcat = GB2_ParmCat(sec) 71 | parmnum = GB2_ParmNum(sec) 72 | 73 | // use_local_table = (mastertab == 255) ? 1 : 0; 74 | use_local_table = mastertab == 255 75 | 76 | if (parmnum >= 192 && parmnum <= 254) || (parmcat >= 192 && parmcat <= 254) || (discipline >= 192 && discipline <= 254) { 77 | use_local_table = true 78 | } 79 | 80 | if use_local_table && localtab == 0 { 81 | //return nil, fprintf("**** ERROR: local table = 0 is not allowed, set to 1 ***\n") 82 | localtab = 1 83 | } 84 | if use_local_table && localtab == 255 { 85 | return nil, fatal_error("local gribtable is undefined (255)", "") 86 | } 87 | 88 | if !use_local_table { 89 | for _, p := range gts { 90 | if discipline == p.disc && (mastertab >= p.mtab_low) && (mastertab <= p.mtab_high) && 91 | parmcat == p.pcat && parmnum == p.pnum { 92 | return &p, nil 93 | } 94 | } 95 | } else { 96 | // printf(">> cname local find: disc %d center %d localtab %d pcat %d pnum %d\n", discipline, center, localtab, parmcat, parmnum); 97 | for _, p := range gts { 98 | if discipline == p.disc && center == p.cntr && localtab == p.ltab && parmcat == p.pcat && parmnum == p.pnum { 99 | return &p, nil 100 | } 101 | } 102 | } 103 | return nil, nil 104 | } 105 | -------------------------------------------------------------------------------- /reader.go: -------------------------------------------------------------------------------- 1 | package grib2 2 | 3 | import ( 4 | "encoding/binary" 5 | "time" 6 | 7 | "github.com/amsokol/go-grib2/internal" 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | // GRIB2 is simplified GRIB2 file structure 12 | type GRIB2 struct { 13 | RefTime time.Time 14 | VerfTime time.Time 15 | Name string 16 | Description string 17 | Unit string 18 | Level string 19 | Values []Value 20 | } 21 | 22 | // Value is data item of GRIB2 file 23 | type Value struct { 24 | Longitude float64 25 | Latitude float64 26 | Value float32 27 | } 28 | 29 | // Read reads raw GRIB2 files and return slice of structured GRIB2 data 30 | func Read(data []byte) ([]GRIB2, error) { 31 | if data == nil { 32 | return nil, errors.New("Raw data is nil") 33 | } 34 | 35 | dlen := len(data) 36 | 37 | if dlen < 4 { 38 | return nil, errors.New("Raw data should be 4 bytes at least") 39 | } 40 | 41 | gribs := []GRIB2{} 42 | 43 | start := 0 44 | eod := false 45 | for !eod { 46 | if string(data[0:4]) != "GRIB" { 47 | return nil, errors.New("First 4 bytes of raw data must be 'GRIB'") 48 | } 49 | 50 | grib := GRIB2{ 51 | Values: []Value{}, 52 | } 53 | 54 | sections := [][]byte{nil, nil, nil, nil, nil, nil, nil, nil} 55 | 56 | size := 16 57 | sections[0] = data[start : start+size] 58 | start += size 59 | 60 | prv := -1 61 | cur := 0 62 | eof := false 63 | for !eof { 64 | prv = cur 65 | if prv == 7 { 66 | // block is read -> export data to values 67 | 68 | grib.RefTime = internal.RefTime(sections) 69 | 70 | var err error 71 | grib.VerfTime, err = internal.VerfTime(sections) 72 | if err != nil { 73 | return nil, errors.Wrapf(err, "Failed to get VerfTime") 74 | } 75 | 76 | grib.Name, grib.Description, grib.Unit, err = internal.GetInfo(sections) 77 | if err != nil { 78 | return nil, errors.Wrapf(err, "Failed to GetInfo") 79 | } 80 | 81 | grib.Level, err = internal.GetLevel(sections) 82 | if err != nil { 83 | return nil, errors.Wrapf(err, "Failed to GetLevel") 84 | } 85 | 86 | var lon, lat []float64 87 | err = internal.LatLon(sections, &lon, &lat) 88 | if err != nil { 89 | return nil, errors.Wrapf(err, "Failed to get longitude and latitude") 90 | } 91 | raw, err := internal.UnpackData(sections) 92 | if err != nil { 93 | return nil, errors.Wrapf(err, "Failed to unpack data") 94 | } 95 | c := len(lon) 96 | v := make([]Value, c, c) 97 | for i := 0; i < c; i++ { 98 | v[i].Longitude = lon[i] 99 | v[i].Latitude = lat[i] 100 | v[i].Value = raw[i] 101 | } 102 | 103 | grib.Values = append(grib.Values, v...) 104 | 105 | sections[2] = nil 106 | sections[3] = nil 107 | sections[4] = nil 108 | sections[5] = nil 109 | sections[6] = nil 110 | sections[7] = nil 111 | 112 | if string(data[start:start+4]) == "7777" { 113 | eof = true 114 | size = 4 115 | } 116 | } else { 117 | size = int(binary.BigEndian.Uint32(data[start:])) 118 | cur = int(data[start+4]) 119 | sections[cur] = data[start : start+size] 120 | } 121 | start += size 122 | } 123 | 124 | gribs = append(gribs, grib) 125 | 126 | if start == dlen { 127 | eod = true 128 | } 129 | } 130 | 131 | return gribs, nil 132 | } 133 | -------------------------------------------------------------------------------- /internal/Code_Values.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | func stat_proc_verf_time(sec [][]unsigned_char, year *int, month *int, day *int, hour *int, minute *int, second *int) int { 4 | var stat_proc_time []unsigned_char 5 | 6 | stat_proc_time = stat_proc_verf_time_location(sec) 7 | 8 | if stat_proc_time != nil { 9 | get_time(stat_proc_time, year, month, day, hour, minute, second) 10 | return 0 11 | } 12 | *year = 0 13 | *month = 0 14 | *day = 0 15 | *hour = 0 16 | *minute = 0 17 | *second = 0 18 | 19 | return 1 20 | } 21 | 22 | /* 23 | * returns location of statistical time processing section 24 | * ie location of overall time 25 | * 26 | */ 27 | func stat_proc_verf_time_location(sec [][]unsigned_char) []unsigned_char { 28 | var i, j, center, nb int 29 | i = code_table_4_0(sec) 30 | center = GB2_Center(sec) 31 | j = 0 32 | if i == 8 { 33 | j = 34 34 | } else if i == 9 { 35 | j = 47 36 | } else if i == 10 { 37 | j = 35 38 | } else if i == 11 { 39 | j = 37 40 | } else if i == 12 { 41 | j = 36 42 | } else if i == 13 { 43 | j = 68 44 | } else if i == 14 { 45 | j = 64 46 | } else if i == 34 { 47 | nb = int(sec[4][22]) 48 | j = 26 + 11*nb 49 | } else if i == 42 { 50 | j = 36 51 | } else if i == 43 { 52 | j = 39 53 | } else if i == 46 { 54 | j = 47 55 | } else if i == 47 { 56 | j = 50 57 | } else if i == 61 { 58 | j = 44 59 | } else if i == 50008 && (center == JMA1 || center == JMA2) { 60 | j = 34 61 | } 62 | if j == 0 { 63 | return nil 64 | } 65 | return sec[4][j:] 66 | } 67 | 68 | /* 69 | * returns number of particle size distributions used by template 4.57 70 | */ 71 | func number_of_mode(sec [][]unsigned_char) int { 72 | var pdt int 73 | pdt = code_table_4_0(sec) 74 | if pdt == 57 { 75 | return int(uint2(sec[4][13:])) 76 | } 77 | return -1 78 | } 79 | 80 | /* 81 | * forecast_time_in_units 82 | * 83 | * v1.1 4/2015: allow forecast time to be a signed quantity 84 | * old: return unsigned value, ! code_4_4, return 0xffffffff; 85 | * new: return signed value ! code_4_4, return 0 86 | */ 87 | func forecast_time_in_units(sec [][]unsigned_char) int { 88 | 89 | var code_4_4 []unsigned_char 90 | var pdt int 91 | 92 | code_4_4 = code_table_4_4_location(sec) 93 | if code_4_4 != nil { 94 | // silly WMO codes group 95 | pdt = code_table_4_0(sec) 96 | if pdt != 44 { 97 | return int4(code_4_4[1:]) 98 | } 99 | return int2(code_4_4[1:]) 100 | } 101 | return 0 102 | // return 0xffffffff; 103 | } 104 | 105 | func fixed_surfaces(sec [][]unsigned_char, type1 *int, surface1 *float, undef_val1 *int, type2 *int, surface2 *float, undef_val2 *int) error { 106 | 107 | var p1, p2 []unsigned_char 108 | *undef_val1 = 1 109 | *undef_val2 = 1 110 | *surface1 = UNDEFINED 111 | *surface2 = UNDEFINED 112 | *type1 = 255 113 | *type2 = 255 114 | 115 | p1, err := code_table_4_5a_location(sec) 116 | if err != nil { 117 | fatal_error_wrap(err, "Failed to execute code_table_4_5a_location") 118 | } 119 | p2, err = code_table_4_5b_location(sec) 120 | if err != nil { 121 | fatal_error_wrap(err, "Failed to execute code_table_4_5b_location") 122 | } 123 | 124 | if p1 != nil && p1[0] != 255 { 125 | *type1 = int(p1[0]) 126 | if p1[1] != 255 { 127 | if p1[2] != 255 || p1[3] != 255 || p1[4] != 255 || p1[5] != 255 { 128 | *undef_val1 = 0 129 | *surface1 = scaled2flt(INT1(p1[1]), int4(p1[2:])) 130 | } 131 | } 132 | } 133 | if p2 != nil && p2[0] != 255 { 134 | *type2 = int(p2[0]) 135 | if p2[1] != 255 { 136 | if p2[2] != 255 || p2[3] != 255 || p2[4] != 255 || p2[5] != 255 { 137 | *undef_val2 = 0 138 | *surface2 = scaled2flt(INT1(p2[1]), int4(p2[2:])) 139 | } 140 | } 141 | } 142 | return nil 143 | } 144 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GRIB2 library for Go programming language (golang) 2 | 3 | ## History 4 | 5 | Once upon time I had a need to read the GRIB2 file in golang. I used Google search and found the following libraries: 6 | 7 | - [https://github.com/analogic/grib](https://github.com/analogic/grib) - obsolete 8 | - [https://github.com/brockwood/gogrib2](https://github.com/brockwood/gogrib2) - empty 9 | - [https://github.com/nilsmagnus/grib](https://github.com/nilsmagnus/grib) 10 | 11 | Library `nilsmagnus/grib` looked reassuringly. I downloaded [gfs.t00z.pgrb2.0p25.f001](http://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25_1hr.pl?file=gfs.t00z.pgrb2.0p25.f001&lev_10_m_above_ground=on&var_UGRD=on&var_VGRD=on&subregion=&leftlon=-10&rightlon=19&toplat=60&bottomlat=35.7&dir=%2Fgfs.2017072000) file from `nomads.ncep.noaa.gov`, ran `grib` export and got error `format is not supported` (((. 12 | 13 | I decided to develop GRIB2 library by myself. I looked at `nilsmagnus/grib` and libraries for Java and Python. All libraries are attempts to understand how GRIB2 is arranged inside and to develop GRIB2 engine using appropriated programming language. 14 | 15 | There was the reference GRIB2 implementation - [wgrib2](http://www.cpc.ncep.noaa.gov/products/wesley/wgrib2/) tool. Look at `wgrib2` source code. It's a lot of "crazy" `C` language code ))). As for me it's very difficult to understand how it works in details. There was the way to call `wgrib2` from golang application. But I rejected that due to the following reasons: 16 | 17 | - `wgrib2` is not thread-safe. There are a lot of global read/write variables inside code. 18 | 19 | - I prefer pure golang libraries 20 | 21 | I saw the only one way - to port `wgrib2` to golang. I did not want to repeat approach of another libraries. I was not going to rewrite `wgrib2` to golang. I decided to port `wgrib2` engine `C` code to `golang` with minimal correction and develop simple wrapper. I used results of `wgrib2` export to CSV as the reference for testing. That approach allows: 22 | 23 | - safe time (porting spent few days only) 24 | - easy apply new features and patches from original `wgrib2` development stream 25 | 26 | I used `grib2-v2.0.6c` version. Here is the result of my work. The work is on final stage. 27 | 28 | ## How-to 29 | 30 | ```bash 31 | go get -u github.com/amsokol/go-grib2 32 | ``` 33 | 34 | It contains only one function that reads GRIB2 file: 35 | 36 | ```go 37 | func Read(data []byte) ([]GRIB2, error) 38 | ``` 39 | 40 | where `GRIB2` is the structure with parsed data: 41 | 42 | ```go 43 | // GRIB2 is simplified GRIB2 file structure 44 | type GRIB2 struct { 45 | RefTime time.Time 46 | VerfTime time.Time 47 | Name string 48 | Description string 49 | Unit string 50 | Level string 51 | Values []Value 52 | } 53 | 54 | // Value is data item of GRIB2 file 55 | type Value struct { 56 | Longitude float64 57 | Latitude float64 58 | Value float32 59 | } 60 | ``` 61 | 62 | Unlike `wgrib2` It's thread-safe. 63 | 64 | See the following usage examples: 65 | 66 | - [file-grib2csv](https://github.com/amsokol/go-grib2/tree/master/cmd/examples/file-grib2csv) - export GRIB2 file to CSV 67 | - [http-grib2csv](https://github.com/amsokol/go-grib2/tree/master/cmd/examples/http-grib2csv) - export `nomads.ncep.noaa.gov` HTTP response to CSV 68 | 69 | ## Roadmap 70 | 71 | Major work is finished. `go-grib2` is ready to use. I have a little bit to port: 72 | 73 | - parse `longitude` and `latitude` are stored as `gauss`, `space_view`, `irr_grid` 74 | - parse data are stored using `complex` and `run_length` algorithms 75 | 76 | ## Issues 77 | 78 | `go-grib2` does not support `jpeg`, `png` and `aec` data package formats. The reason is `wgrib2` uses external `C` libraries to read these formats. If you have an idea how to easy port `jpeg`, `png` and `aec` please let me know. 79 | 80 | ## Need help 81 | 82 | I need help is testing. Please test `go-grib2` with several GRIB2 files from several providers. Use `wgrib2` CSV export to validate results. Please create issues here. 83 | 84 | # If you need fully functional GRIB2 library look at the my golang wrapper for ecCodes 85 | [go-eccodes](https://github.com/amsokol/go-eccodes) 86 | 87 | -------------------------------------------------------------------------------- /internal/unpk.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | * unpack grib -- only some formats (code table 5.0) are supported 5 | * 6 | * supported: 0 (simple), 4 (ieee), 40 (jpeg), 41(png), 42(aec) 7 | * 8 | * input: sec[] 9 | * float data[npnts] 10 | * 11 | */ 12 | func unpk_grib(sec [][]unsigned_char, data []float) error { 13 | 14 | var packing, bitmap_flag, nbits int 15 | var ndata, ii unsigned_int 16 | var mask_pointer []unsigned_char 17 | var mask unsigned_char 18 | var ieee, p []unsigned_char 19 | var tmp float 20 | // float reference, tmp; 21 | var reference double 22 | var bin_scale, dec_scale, b double 23 | 24 | packing = code_table_5_0(sec) 25 | // ndata = (int) GB2_Sec3_npts(sec); 26 | ndata = GB2_Sec3_npts(sec) 27 | bitmap_flag = code_table_6_0(sec) 28 | 29 | if bitmap_flag != 0 && bitmap_flag != 254 && bitmap_flag != 255 { 30 | return fatal_error("unknown bitmap", "") 31 | } 32 | 33 | if packing == 4 { // ieee 34 | if sec[5][11] != 1 { 35 | return fatal_error_i("unpk ieee grib file precision %d not supported", int(sec[5][11])) 36 | } 37 | 38 | // ieee depacking -- simple no bitmap 39 | if bitmap_flag == 255 { 40 | for ii = 0; ii < ndata; ii++ { 41 | data[ii] = ieee2flt_nan(sec[7][5+ii*4:]) 42 | } 43 | return nil 44 | } 45 | if bitmap_flag == 0 || bitmap_flag == 254 { 46 | mask_pointer = sec[6][6:] 47 | ieee = sec[7][5:] 48 | ieee_index := 0 49 | mask = 0 50 | mask_pointer_index := 0 51 | for ii = 0; ii < ndata; ii++ { 52 | if (ii & 7) == 0 { 53 | mask = mask_pointer[mask_pointer_index] 54 | mask_pointer_index++ 55 | } 56 | if (mask & 128) != 0 { 57 | data[ii] = ieee2flt_nan(ieee[ieee_index:]) 58 | ieee_index += 4 59 | } else { 60 | data[ii] = UNDEFINED 61 | } 62 | mask <<= 1 63 | } 64 | return nil 65 | } 66 | return fatal_error("unknown bitmap", "") 67 | } else if packing == 0 || packing == 61 { // simple grib1 packing 61 -- log preprocessing 68 | 69 | p = sec[5] 70 | reference = double(ieee2flt(p[11:])) 71 | bin_scale = Int_Power(2.0, int2(p[15:])) 72 | dec_scale = Int_Power(10.0, -int2(p[17:])) 73 | nbits = int(p[19]) 74 | b = 0.0 75 | if packing == 61 { 76 | b = double(ieee2flt(p[20:])) 77 | } 78 | 79 | if bitmap_flag != 0 && bitmap_flag != 254 && bitmap_flag != 255 { 80 | return fatal_error("unknown bitmap", "") 81 | } 82 | 83 | if nbits == 0 { 84 | tmp = float(reference * dec_scale) 85 | if packing == 61 { 86 | tmp = float(exp(double(tmp)) - b) 87 | } // remove log prescaling 88 | if bitmap_flag == 255 { 89 | for ii = 0; ii < ndata; ii++ { 90 | data[ii] = tmp 91 | } 92 | return nil 93 | } 94 | if bitmap_flag == 0 || bitmap_flag == 254 { 95 | mask_pointer = sec[6][6:] 96 | mask = 0 97 | mask_pointer_index := 0 98 | for ii = 0; ii < ndata; ii++ { 99 | if (ii & 7) == 0 { 100 | mask = mask_pointer[mask_pointer_index] 101 | mask_pointer_index++ 102 | } 103 | // data[ii] = (mask & 128) ? tmp : UNDEFINED; 104 | if (mask & 128) != 0 { 105 | data[ii] = tmp 106 | } else { 107 | data[ii] = UNDEFINED 108 | } 109 | mask <<= 1 110 | } 111 | return nil 112 | } 113 | } 114 | 115 | // mask_pointer = (bitmap_flag == 255) ? NULL : sec[6] + 6; 116 | if bitmap_flag == 255 { 117 | mask_pointer = nil 118 | } else { 119 | mask_pointer = sec[6][6:] 120 | } 121 | 122 | unpk_0(data, sec[7][5:], mask_pointer, nbits, ndata, reference, 123 | bin_scale, dec_scale) 124 | 125 | if packing == 61 { // remove log prescaling 126 | // #pragma omp parallel for private(ii) schedule(static) 127 | for ii = 0; ii < ndata; ii++ { 128 | if DEFINED_VAL(data[ii]) { 129 | data[ii] = float(exp(double(data[ii])) - b) 130 | } 131 | } 132 | } 133 | return nil 134 | } else if packing == 2 || packing == 3 { // complex 135 | return fatal_error("unpk_complex is not supported") 136 | // TODO: unpk_complex 137 | // return unpk_complex(sec, data, ndata) 138 | } else if packing == 200 { // run length 139 | return fatal_error("unpk_run_length is not supported") 140 | // TODO: unpk_run_length 141 | // return unpk_run_length(sec, data, ndata) 142 | } 143 | return fatal_error_i("packing type %d not supported", packing) 144 | } 145 | -------------------------------------------------------------------------------- /internal/VerfTime.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | int reftime(unsigned char **sec, int *year, int *month, int *day, int *hour, int *minute, int *second) 5 | { 6 | 7 | unsigned char *p; 8 | 9 | p = sec[1]; 10 | *year = (p[12] << 8) | p[13]; 11 | *month = p[14]; 12 | *day = p[15]; 13 | *hour = p[16]; 14 | *minute = p[17]; 15 | *second = p[18]; 16 | 17 | return 0; 18 | } 19 | */ 20 | func reftime(sec [][]unsigned_char, year *int, month *int, day *int, hour *int, minute *int, second *int) { 21 | var p []unsigned_char 22 | 23 | p = sec[1] 24 | *year = (int(p[12]) << 8) | int(p[13]) 25 | *month = int(p[14]) 26 | *day = int(p[15]) 27 | *hour = int(p[16]) 28 | *minute = int(p[17]) 29 | *second = int(p[18]) 30 | } 31 | 32 | /* 33 | * Returns the verification time: reference_time + forecast_time + statistical processing time (if any) 34 | * 9/2006 w. ebisuzaki 35 | * 1/2007 w. ebisuzaki return error code 36 | * 11/2007 w. ebisuzaki fixed code for non forecasts 37 | * 3/2008 w. ebisuzaki added code for ensemble processing 38 | * 4/2009 w. ebisuzaki test table 1.2 sign of reference time 39 | */ 40 | /* 41 | int verftime(unsigned char **sec, int *year, int *month, int *day, int *hour, int *minute, int *second) { 42 | 43 | int units, i, j; 44 | int dtime; 45 | static int error_count = 0; 46 | static int warning_count = 0; 47 | 48 | i = code_table_4_0(sec); 49 | 50 | // if statistically processed field, verftime is in header 51 | j = stat_proc_verf_time(sec, year, month, day, hour, minute, second); 52 | if (j == 0) return 0; 53 | 54 | get_time(sec[1]+12, year, month, day, hour, minute, second); 55 | 56 | // some products have no forecast time 57 | 58 | if (code_table_4_4(sec) == -1) return 0; 59 | 60 | // check the significance of the refernce time 61 | i = code_table_1_2(sec); 62 | 63 | if (i == 2) { 64 | // rt=verifying time of forecast 65 | // unclear what it means for time averages/accumulations 66 | if (warning_count == 0) { 67 | fprintf(stderr,"Warning: rt == vt (CodeTable 1.2)\n"); 68 | warning_count++; 69 | } 70 | return 0; 71 | } 72 | if (i == 3) { 73 | // rt = observing time 74 | return 0; 75 | } 76 | 77 | if (i != 0 && i != 1) { 78 | if (error_count == 0) { 79 | fprintf(stderr,"verifying time: Table 1.2=%d not supported " 80 | " using RT=analysis/start of forecast\n", i); 81 | error_count++; 82 | } 83 | } 84 | 85 | units = code_table_4_4(sec); 86 | dtime = forecast_time_in_units(sec); 87 | if (dtime >= 0) 88 | return add_time(year, month, day, hour, minute, second, (unsigned int) dtime, units); 89 | return sub_dt(year, month, day, hour, minute, second, (unsigned int) (unsigned int) -dtime, units); 90 | } 91 | */ 92 | 93 | func verftime(sec [][]unsigned_char, year *int, month *int, day *int, hour *int, minute *int, second *int) error { 94 | var units, i, j int 95 | var dtime int 96 | 97 | i = code_table_4_0(sec) 98 | 99 | // if statistically processed field, verftime is in header 100 | j = stat_proc_verf_time(sec, year, month, day, hour, minute, second) 101 | if j == 0 { 102 | return nil 103 | } 104 | 105 | get_time(sec[1][12:], year, month, day, hour, minute, second) 106 | 107 | // some products have no forecast time 108 | 109 | if code_table_4_4(sec) == -1 { 110 | return nil 111 | } 112 | 113 | // check the significance of the reference time 114 | i = code_table_1_2(sec) 115 | 116 | if i == 2 { 117 | // rt=verifying time of forecast 118 | // unclear what it means for time averages/accumulations 119 | /* 120 | if warning_count == 0 { 121 | fprintf(stderr, "Warning: rt == vt (CodeTable 1.2)\n") 122 | warning_count++ 123 | } 124 | */ 125 | return nil 126 | } 127 | if i == 3 { 128 | // rt = observing time 129 | return nil 130 | } 131 | 132 | if i != 0 && i != 1 { 133 | return fprintf("verifying time: Table 1.2=%d not supported using RT=analysis/start of forecast\n", i) 134 | } 135 | 136 | units = code_table_4_4(sec) 137 | dtime = forecast_time_in_units(sec) 138 | if dtime != 0 { 139 | add_time(year, month, day, hour, minute, second, dtime, units) 140 | } 141 | return nil 142 | } 143 | -------------------------------------------------------------------------------- /internal/stagger.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | * stagger fills x[] and y[], lo1 and la1 have X==0 and Y==0 5 | * 6 | * assumed_npnts is number if grid points that the calling program thinks is right 7 | * this is for error checking. use -1 if don't know 8 | * 9 | * to a grid transform: 10 | * setup grid transform (proj4 library for example( 11 | * call stagger() to get the x() and y() values of the grid 12 | * transform x() and y() to lon() and lat() 13 | * 14 | * like many programs, stagger requires grid to be on we:sn order 15 | */ 16 | func stagger(sec [][]unsigned_char, assumed_npnts unsigned_int, x []double, y []double, n_variable_dim *int, variable_dim *[]int, raw_variable_dim *[]int) error { 17 | var nx, ny, res, scan int 18 | var npnts unsigned_int 19 | var nnx, nx_even, nx_odd, nx2 int 20 | var x0, y0, dx_offset, dx_offset_even, dx_offset_odd, dy_offset double 21 | var i, ix, iy, n unsigned_int 22 | 23 | var reduced_grid, dx_off_odd, dx_off_even, dy_off int 24 | var dx, dy, even int 25 | 26 | get_nxny(sec, &nx, &ny, &npnts, &res, &scan, n_variable_dim, variable_dim, raw_variable_dim) 27 | if scan == -1 { 28 | return fatal_error("scan == -1") 29 | } 30 | if output_order != wesn { 31 | return fatal_error("output_order != wesn") 32 | } 33 | if nx < 1 || ny < 1 { 34 | return fatal_error("nx < 1 || ny < 1") 35 | } 36 | 37 | /* get stagger bits */ 38 | dx_off_odd = int((unsigned_int(scan) >> 3) & 1) 39 | dx_off_even = int((unsigned_int(scan) >> 2) & 1) 40 | dy_off = int((unsigned_int(scan) >> 1) & 1) 41 | reduced_grid = int(unsigned_int(scan) & 1) 42 | 43 | // dx = (scan & 128) ? -1 : 1; 44 | if (scan & 128) != 0 { 45 | dx = -1 46 | } else { 47 | dx = 1 48 | } 49 | // dy = (scan & 64) ? 1 : -1; 50 | if (scan & 64) != 0 { 51 | dy = 1 52 | } else { 53 | dy = -1 54 | } 55 | 56 | if reduced_grid != 0 && dy_off != 0 { 57 | ny-- 58 | } 59 | 60 | if dy < 0 && ((ny % 2) == 0) { // swap even and odd rows if ns to sn and even number of rows 61 | i = unsigned_int(dx_off_odd) 62 | dx_off_odd = dx_off_even 63 | dx_off_even = int(i) 64 | } 65 | 66 | // dx_offset_odd = reduced_grid ? 0.5 * dx_off_odd : 0.5 * dx_off_odd * dx; 67 | if reduced_grid != 0 { 68 | dx_offset_odd = 0.5 * double(dx_off_odd) 69 | } else { 70 | dx_offset_odd = 0.5 * double(dx_off_odd) * double(dx) 71 | } 72 | // dx_offset_even = reduced_grid ? 0.5 * dx_off_even : 0.5 * dx_off_even * dx; 73 | if reduced_grid != 0 { 74 | dx_offset_even = 0.5 * double(dx_off_even) 75 | } else { 76 | dx_offset_even = 0.5 * double(dx_off_even) * double(dx) 77 | } 78 | // dy_offset = reduced_grid ? 0.5 * dy_off : 0.5 * dy_off * dy; 79 | if reduced_grid != 0 { 80 | dy_offset = 0.5 * double(dy_off) 81 | } else { 82 | dy_offset = 0.5 * double(dy_off) * double(dy) 83 | } 84 | 85 | nx_odd = nx - (dx_off_odd & reduced_grid) 86 | nx_even = nx - (dx_off_even & reduced_grid) 87 | nx2 = nx_odd + nx_even 88 | 89 | //fprintf(stderr, "stagger: dx_off_odd %lf dx_off_even %lf dy_off %lf reduced_grid %d nx=%d %d\n", 90 | // dx_offset_odd, dx_offset_even, dy_offset, reduced_grid, nx_odd,nx_even); 91 | //fprintf(stderr,"dx_off_odd %d reduced_grid %d, and %d\n", dx_off_odd , reduced_grid, dx_off_odd & reduced_grid); 92 | //fprintf(stderr,"dx_off_even %d reduced_grid %d, and %d\n", dx_off_even , reduced_grid, dx_off_even & reduced_grid); 93 | 94 | // number of grid points 95 | n = unsigned_int((ny/2)*nx_even + ((ny+1)/2)*nx_odd) 96 | 97 | // check to number of points 98 | if assumed_npnts != n { 99 | return fatal_error_ii("stagger: program error think npnts=%d assumed npnts=%d", n, int(assumed_npnts)) 100 | } 101 | if n != GB2_Sec3_npts(sec) { 102 | return fatal_error_ii("stagger: program error think npnts=%d, Sec3 gives %d", n, GB2_Sec3_npts(sec)) 103 | } 104 | 105 | if x == nil || y == nil { 106 | return fatal_error("x == nil || y == nil") 107 | } 108 | 109 | /* return X[] and Y[] relative to the first grid point but on a we:sn grid */ 110 | 111 | // x0 = (dx > 0) ? 0.0 : 1.0 - (double) nx; 112 | if dx > 0 { 113 | x0 = 0.0 114 | } else { 115 | x0 = 1.0 - double(nx) 116 | } 117 | //y0 = (dy > 0) ? 0.0 : 1.0 - (double) ny; 118 | if dy > 0 { 119 | y0 = 0.0 120 | } else { 121 | y0 = 1.0 - double(ny) 122 | } 123 | 124 | for iy = 0; iy < unsigned_int(ny); iy++ { 125 | // even = iy % 2; // first row is odd .. iy % 2 == 0 126 | even = int(iy & 1) // first row is odd 127 | //i = even ? nx2*(iy >> 1) + nx_odd : nx2*(iy >> 1); 128 | if even != 0 { 129 | i = unsigned_int(nx2)*(iy>>1) + unsigned_int(nx_odd) 130 | } else { 131 | i = unsigned_int(nx2) * (iy >> 1) 132 | } 133 | //nnx = even ? nx_even : nx_odd; 134 | if even != 0 { 135 | nnx = nx_even 136 | } else { 137 | nnx = nx_odd 138 | } 139 | //dx_offset = even ? dx_offset_even : dx_offset_odd; 140 | if even != 0 { 141 | dx_offset = dx_offset_even 142 | } else { 143 | dx_offset = dx_offset_odd 144 | } 145 | for ix = 0; ix < unsigned_int(nnx); ix++ { 146 | x[i+ix] = x0 + dx_offset + double(ix) 147 | y[i+ix] = y0 + dy_offset + double(iy) 148 | } 149 | } 150 | 151 | return nil 152 | } 153 | -------------------------------------------------------------------------------- /internal/stubs.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "fmt" 5 | "math" 6 | "time" 7 | "unsafe" 8 | 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | type unsigned_char byte 13 | type char byte 14 | type unsigned_int uint 15 | type double float64 16 | type float float32 17 | type size_t unsigned_int 18 | 19 | /* 20 | unsigned int uint4(unsigned const char *p) { 21 | return ((p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]); 22 | } 23 | */ 24 | func uint4(p []unsigned_char) unsigned_int { 25 | return ((unsigned_int(p[0]) << 24) + (unsigned_int(p[1]) << 16) + (unsigned_int(p[2]) << 8) + unsigned_int(p[3])) 26 | } 27 | 28 | /* 29 | int int4(unsigned const char *p) { 30 | int i; 31 | if (p[0] & 0x80) { 32 | i = -(((p[0] & 0x7f) << 24) + (p[1] << 16) + (p[2] << 8) + p[3]); 33 | } 34 | else { 35 | i = (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; 36 | } 37 | return i; 38 | } 39 | */ 40 | func int4(p []unsigned_char) int { 41 | var i int 42 | if (p[0] & 0x80) != 0 { 43 | i = -(((int(p[0]) & 0x7f) << 24) + (int(p[1]) << 16) + (int(p[2]) << 8) + int(p[3])) 44 | } else { 45 | i = (int(p[0]) << 24) + (int(p[1]) << 16) + (int(p[2]) << 8) + int(p[3]) 46 | } 47 | return i 48 | } 49 | 50 | func fabs(v double) double { 51 | return double(math.Abs(float64(v))) 52 | } 53 | 54 | func ldexp(frac double, exp int) double { 55 | return double(math.Ldexp(float64(frac), exp)) 56 | } 57 | 58 | func pow(x, y double) double { 59 | return double(math.Pow(float64(x), float64(y))) 60 | } 61 | 62 | func sqrt(x double) double { 63 | return double(math.Sqrt(float64(x))) 64 | } 65 | 66 | func Int_Power(x double, y int) double { 67 | return double(math.Pow(float64(x), float64(y))) 68 | } 69 | 70 | func exp(v double) double { 71 | return double(math.Exp(float64(v))) 72 | } 73 | 74 | func sin(v double) double { 75 | return double(math.Sin(float64(v))) 76 | } 77 | 78 | func cos(v double) double { 79 | return double(math.Cos(float64(v))) 80 | } 81 | 82 | func asin(v double) double { 83 | return double(math.Asin(float64(v))) 84 | } 85 | 86 | func atan2(x, y double) double { 87 | return double(math.Atan2(float64(x), float64(y))) 88 | } 89 | 90 | func log(v double) double { 91 | return double(math.Log(float64(v))) 92 | } 93 | 94 | func tan(v double) double { 95 | return double(math.Tan(float64(v))) 96 | } 97 | 98 | func atan(v double) double { 99 | return double(math.Atan(float64(v))) 100 | } 101 | 102 | func fatal_error(format string, args ...interface{}) error { 103 | return errors.Errorf(format, args) 104 | } 105 | 106 | func fatal_error_ii(format string, args ...interface{}) error { 107 | return errors.Errorf(format, args) 108 | } 109 | 110 | func fatal_error_i(format string, args ...interface{}) error { 111 | return errors.Errorf(format, args) 112 | } 113 | 114 | func fatal_error_wrap(err error, format string, args ...interface{}) error { 115 | return errors.Wrapf(err, format, args) 116 | } 117 | 118 | func fprintf(format string, args ...interface{}) error { 119 | return errors.Errorf(format, args...) 120 | } 121 | 122 | func sprintf(format string, args ...interface{}) string { 123 | return fmt.Sprintf(format, args...) 124 | } 125 | 126 | func LatLon(sec [][]byte, lon *[]float64, lat *[]float64) error { 127 | g_sec := *(*[][]unsigned_char)(unsafe.Pointer(&sec)) 128 | g_lon := *(**[]double)(unsafe.Pointer(&lon)) 129 | g_lat := *(**[]double)(unsafe.Pointer(&lat)) 130 | 131 | return get_latlon(g_sec, g_lon, g_lat) 132 | } 133 | 134 | func UnpackData(sec [][]byte) ([]float32, error) { 135 | g_sec := *(*[][]unsigned_char)(unsafe.Pointer(&sec)) 136 | 137 | ndata := GB2_Sec3_npts(g_sec) 138 | g_data := make([]float, ndata) 139 | err := unpk_grib(g_sec, g_data) 140 | if err != nil { 141 | return nil, err 142 | } 143 | 144 | return *(*[]float32)(unsafe.Pointer(&g_data)), nil 145 | } 146 | 147 | func RefTime(sec [][]byte) time.Time { 148 | var year, month, day, hour, minute, second int 149 | 150 | g_sec := *(*[][]unsigned_char)(unsafe.Pointer(&sec)) 151 | reftime(g_sec, &year, &month, &day, &hour, &minute, &second) 152 | 153 | return time.Date(year, time.Month(month), day, hour, minute, second, 0, time.UTC) 154 | } 155 | 156 | func VerfTime(sec [][]byte) (time.Time, error) { 157 | var year, month, day, hour, minute, second int 158 | 159 | g_sec := *(*[][]unsigned_char)(unsafe.Pointer(&sec)) 160 | 161 | err := verftime(g_sec, &year, &month, &day, &hour, &minute, &second) 162 | if err != nil { 163 | return time.Now(), errors.Wrapf(err, "Failed to run verftime") 164 | } 165 | 166 | return time.Date(year, time.Month(month), day, hour, minute, second, 0, time.UTC), nil 167 | } 168 | 169 | func GetInfo(sec [][]byte) (name string, desc string, unit string, err error) { 170 | g_sec := *(*[][]unsigned_char)(unsafe.Pointer(&sec)) 171 | 172 | err = getName(g_sec, &name, &desc, &unit) 173 | if err != nil { 174 | return "", "", "", errors.Wrapf(err, "Failed to execute getName") 175 | } 176 | return name, desc, unit, nil 177 | } 178 | 179 | func GetLevel(sec [][]byte) (level string, err error) { 180 | g_sec := *(*[][]unsigned_char)(unsafe.Pointer(&sec)) 181 | 182 | err = f_lev(g_sec, &level) 183 | if err != nil { 184 | return "", errors.Wrapf(err, "Failed to execute f_lev") 185 | } 186 | return level, nil 187 | } 188 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/stack.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "path" 7 | "runtime" 8 | "strings" 9 | ) 10 | 11 | // Frame represents a program counter inside a stack frame. 12 | type Frame uintptr 13 | 14 | // pc returns the program counter for this frame; 15 | // multiple frames may have the same PC value. 16 | func (f Frame) pc() uintptr { return uintptr(f) - 1 } 17 | 18 | // file returns the full path to the file that contains the 19 | // function for this Frame's pc. 20 | func (f Frame) file() string { 21 | fn := runtime.FuncForPC(f.pc()) 22 | if fn == nil { 23 | return "unknown" 24 | } 25 | file, _ := fn.FileLine(f.pc()) 26 | return file 27 | } 28 | 29 | // line returns the line number of source code of the 30 | // function for this Frame's pc. 31 | func (f Frame) line() int { 32 | fn := runtime.FuncForPC(f.pc()) 33 | if fn == nil { 34 | return 0 35 | } 36 | _, line := fn.FileLine(f.pc()) 37 | return line 38 | } 39 | 40 | // Format formats the frame according to the fmt.Formatter interface. 41 | // 42 | // %s source file 43 | // %d source line 44 | // %n function name 45 | // %v equivalent to %s:%d 46 | // 47 | // Format accepts flags that alter the printing of some verbs, as follows: 48 | // 49 | // %+s path of source file relative to the compile time GOPATH 50 | // %+v equivalent to %+s:%d 51 | func (f Frame) Format(s fmt.State, verb rune) { 52 | switch verb { 53 | case 's': 54 | switch { 55 | case s.Flag('+'): 56 | pc := f.pc() 57 | fn := runtime.FuncForPC(pc) 58 | if fn == nil { 59 | io.WriteString(s, "unknown") 60 | } else { 61 | file, _ := fn.FileLine(pc) 62 | fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) 63 | } 64 | default: 65 | io.WriteString(s, path.Base(f.file())) 66 | } 67 | case 'd': 68 | fmt.Fprintf(s, "%d", f.line()) 69 | case 'n': 70 | name := runtime.FuncForPC(f.pc()).Name() 71 | io.WriteString(s, funcname(name)) 72 | case 'v': 73 | f.Format(s, 's') 74 | io.WriteString(s, ":") 75 | f.Format(s, 'd') 76 | } 77 | } 78 | 79 | // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). 80 | type StackTrace []Frame 81 | 82 | func (st StackTrace) Format(s fmt.State, verb rune) { 83 | switch verb { 84 | case 'v': 85 | switch { 86 | case s.Flag('+'): 87 | for _, f := range st { 88 | fmt.Fprintf(s, "\n%+v", f) 89 | } 90 | case s.Flag('#'): 91 | fmt.Fprintf(s, "%#v", []Frame(st)) 92 | default: 93 | fmt.Fprintf(s, "%v", []Frame(st)) 94 | } 95 | case 's': 96 | fmt.Fprintf(s, "%s", []Frame(st)) 97 | } 98 | } 99 | 100 | // stack represents a stack of program counters. 101 | type stack []uintptr 102 | 103 | func (s *stack) Format(st fmt.State, verb rune) { 104 | switch verb { 105 | case 'v': 106 | switch { 107 | case st.Flag('+'): 108 | for _, pc := range *s { 109 | f := Frame(pc) 110 | fmt.Fprintf(st, "\n%+v", f) 111 | } 112 | } 113 | } 114 | } 115 | 116 | func (s *stack) StackTrace() StackTrace { 117 | f := make([]Frame, len(*s)) 118 | for i := 0; i < len(f); i++ { 119 | f[i] = Frame((*s)[i]) 120 | } 121 | return f 122 | } 123 | 124 | func callers() *stack { 125 | const depth = 32 126 | var pcs [depth]uintptr 127 | n := runtime.Callers(3, pcs[:]) 128 | var st stack = pcs[0:n] 129 | return &st 130 | } 131 | 132 | // funcname removes the path prefix component of a function's name reported by func.Name(). 133 | func funcname(name string) string { 134 | i := strings.LastIndex(name, "/") 135 | name = name[i+1:] 136 | i = strings.Index(name, ".") 137 | return name[i+1:] 138 | } 139 | 140 | func trimGOPATH(name, file string) string { 141 | // Here we want to get the source file path relative to the compile time 142 | // GOPATH. As of Go 1.6.x there is no direct way to know the compiled 143 | // GOPATH at runtime, but we can infer the number of path segments in the 144 | // GOPATH. We note that fn.Name() returns the function name qualified by 145 | // the import path, which does not include the GOPATH. Thus we can trim 146 | // segments from the beginning of the file path until the number of path 147 | // separators remaining is one more than the number of path separators in 148 | // the function name. For example, given: 149 | // 150 | // GOPATH /home/user 151 | // file /home/user/src/pkg/sub/file.go 152 | // fn.Name() pkg/sub.Type.Method 153 | // 154 | // We want to produce: 155 | // 156 | // pkg/sub/file.go 157 | // 158 | // From this we can easily see that fn.Name() has one less path separator 159 | // than our desired output. We count separators from the end of the file 160 | // path until it finds two more than in the function name and then move 161 | // one character forward to preserve the initial path segment without a 162 | // leading separator. 163 | const sep = "/" 164 | goal := strings.Count(name, sep) + 2 165 | i := len(file) 166 | for n := 0; n < goal; n++ { 167 | i = strings.LastIndex(file[:i], sep) 168 | if i == -1 { 169 | // not enough separators found, set i so that the slice expression 170 | // below leaves file unmodified 171 | i = -len(sep) 172 | break 173 | } 174 | } 175 | // get back to 0 or trim the leading separator 176 | file = file[i+len(sep):] 177 | return file 178 | } 179 | -------------------------------------------------------------------------------- /internal/CodeTable.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | func code_table_1_2(sec [][]unsigned_char) int { 4 | var p []unsigned_char 5 | p = code_table_1_2_location(sec) 6 | if p == nil { 7 | return -1 8 | } 9 | return int(p[0]) 10 | } 11 | 12 | func code_table_1_2_location(sec [][]unsigned_char) []unsigned_char { 13 | return sec[1][11:] 14 | } 15 | 16 | /* 17 | int code_table_3_1(unsigned char **sec) { 18 | return (int) uint2(sec[3]+12); 19 | } 20 | */ 21 | func code_table_3_1(sec [][]unsigned_char) int { 22 | return int(uint2(sec[3][12:])) 23 | } 24 | 25 | func code_table_3_2_location(sec [][]unsigned_char) []unsigned_char { 26 | var grid_def, center int 27 | grid_def = code_table_3_1(sec) 28 | 29 | if grid_def < 50 { 30 | return sec[3][14:] 31 | } 32 | 33 | switch grid_def { 34 | case 90, 110, 130, 140, 204, 1000, 1100: 35 | return sec[3][14:] 36 | default: 37 | } 38 | 39 | center = GB2_Center(sec) 40 | if center == NCEP { 41 | if grid_def == 32768 || (grid_def == 32769) { 42 | return sec[3][14:] 43 | } 44 | } 45 | if (center == JMA1) || (center == JMA2) { 46 | if grid_def == 40110 { 47 | return sec[3][14:] 48 | } 49 | } 50 | return nil 51 | } 52 | 53 | func code_table_4_0(sec [][]unsigned_char) int { 54 | return GB2_ProdDefTemplateNo(sec) 55 | } 56 | 57 | func code_table_4_4(sec [][]unsigned_char) int { 58 | var p []unsigned_char 59 | p = code_table_4_4_location(sec) 60 | if p == nil { 61 | return -1 62 | } 63 | return int(p[0]) 64 | } 65 | 66 | func code_table_4_4_location(sec [][]unsigned_char) []unsigned_char { 67 | var pdt, center, n int 68 | pdt = GB2_ProdDefTemplateNo(sec) 69 | center = GB2_Center(sec) 70 | 71 | switch pdt { 72 | case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 32, 60, 61, 51, 91, 1000, 1001, 1002: 73 | return sec[4][17:] 74 | case 40, 41, 42, 43: 75 | return sec[4][19:] 76 | case 44, 45, 46, 47: 77 | return sec[4][30:] 78 | case 48: 79 | return sec[4][41:] 80 | case 52: 81 | return sec[4][20:] 82 | case 57: 83 | n = number_of_mode(sec) 84 | if n <= 0 || n == 65535 { 85 | return nil 86 | } 87 | return sec[4][26+5*n:] 88 | case 50008: 89 | if center == JMA1 || center == JMA2 { 90 | return sec[4][17:] 91 | } 92 | return nil 93 | case 50009: 94 | if center == JMA1 || center == JMA2 { 95 | return sec[4][17:] 96 | } 97 | return nil 98 | case 50011: 99 | if center == JMA1 || center == JMA2 { 100 | return sec[4][17:] 101 | } 102 | return nil 103 | } 104 | return nil 105 | } 106 | 107 | func code_table_4_5a_location(sec [][]unsigned_char) ([]unsigned_char, error) { 108 | var pdt, center, n int 109 | pdt = GB2_ProdDefTemplateNo(sec) 110 | center = GB2_Center(sec) 111 | 112 | if center == JMA1 || center == JMA2 { 113 | switch pdt { 114 | case 50008: 115 | return sec[4][22:], nil 116 | case 50009: 117 | return sec[4][22:], nil 118 | case 51020, 51021, 51022, 51122, 52020: 119 | return nil, nil 120 | case 50010, 50011: 121 | return sec[4][22:], nil 122 | default: 123 | } 124 | } 125 | 126 | switch pdt { 127 | case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 51, 60, 61, 91, 1100, 1101: 128 | return sec[4][22:], nil 129 | case 40, 41, 42, 43: 130 | return sec[4][24:], nil 131 | case 44: 132 | return sec[4][33:], nil 133 | case 45, 46, 47: 134 | return sec[4][35:], nil 135 | case 48: 136 | return sec[4][46:], nil 137 | case 52: // validation 138 | return sec[4][25:], nil 139 | case 57: 140 | n = number_of_mode(sec) 141 | if n <= 0 || n == 65535 { 142 | return nil, fatal_error_i("PDT 4.57 bad number of mode %d", n) 143 | } 144 | return sec[4][31+5*n:], nil 145 | case 20, 30, 31, 32, 1000, 1001, 1002, 254: 146 | return nil, nil 147 | default: 148 | return nil, fprintf("code_table_4.5a: product definition template #%d not supported\n", pdt) 149 | } 150 | } 151 | 152 | func code_table_4_5b_location(sec [][]unsigned_char) ([]unsigned_char, error) { 153 | var pdt, center, n int 154 | pdt = GB2_ProdDefTemplateNo(sec) 155 | center = GB2_Center(sec) 156 | 157 | if center == JMA1 || center == JMA2 { 158 | switch pdt { 159 | case 50008: 160 | return sec[4][28:], nil 161 | case 50009: 162 | return sec[4][28:], nil 163 | case 51020, 51021, 51022, 51122: 164 | return nil, nil 165 | case 50010: 166 | case 50011: 167 | return sec[4][28:], nil 168 | default: 169 | } 170 | } 171 | 172 | switch pdt { 173 | case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 51, 60, 61, 91, 1100, 1101: 174 | return sec[4][28:], nil 175 | case 40, 41, 42, 43: 176 | return sec[4][30:], nil 177 | case 44: 178 | return sec[4][39:], nil 179 | case 45, 46, 47: 180 | return sec[4][41:], nil 181 | case 48: 182 | return sec[4][52:], nil 183 | case 52: 184 | return nil, nil 185 | case 57: 186 | n = number_of_mode(sec) 187 | if n <= 0 || n == 65535 { 188 | return nil, fatal_error_i("PDT 4.57 bad number of mode %d", n) 189 | } 190 | return sec[4][37+5*n:], nil 191 | case 20, 30, 31, 32, 1000, 1001, 1002, 254: 192 | return nil, nil 193 | default: 194 | return nil, fprintf("code_table_4.5b: product definition template #%d not supported\n", pdt) 195 | } 196 | } 197 | 198 | func code_table_5_0(sec [][]unsigned_char) int { 199 | return int(uint2(sec[5][9:])) 200 | } 201 | 202 | func code_table_6_0(sec [][]unsigned_char) int { 203 | return int(sec[6][5]) 204 | } 205 | -------------------------------------------------------------------------------- /internal/FlagTable.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | int flag_table_3_3(unsigned char **sec) { 5 | unsigned char *p; 6 | p = flag_table_3_3_location(sec); 7 | if (p == NULL) return -1; 8 | return (int) *p; 9 | } 10 | */ 11 | func flag_table_3_3(sec [][]unsigned_char) int { 12 | var p []unsigned_char 13 | p = flag_table_3_3_location(sec) 14 | if p == nil { 15 | return -1 16 | } 17 | return int(p[0]) 18 | } 19 | 20 | /* 21 | unsigned char *flag_table_3_3_location(unsigned char **sec) { 22 | int grid_template, center; 23 | unsigned char *gds; 24 | 25 | grid_template = code_table_3_1(sec); 26 | center = GB2_Center(sec); 27 | gds = sec[3]; 28 | switch (grid_template) { 29 | case 0: 30 | case 1: 31 | case 2: 32 | case 3: 33 | case 40: 34 | case 41: 35 | case 42: 36 | case 43: 37 | case 140: 38 | case 204: 39 | return gds+54; break; 40 | case 4: 41 | case 5: 42 | case 10: 43 | case 12: 44 | case 20: 45 | case 30: 46 | case 31: 47 | case 90: 48 | case 110: 49 | return gds+46; break; 50 | case 32768: 51 | if (center == NCEP) return gds+54; 52 | return NULL; 53 | case 32769: 54 | if (center == NCEP) return gds+54; 55 | return NULL; 56 | case 40110: 57 | if ((center == JMA1) || (center == JMA2)) return gds+46; 58 | return NULL; 59 | break; 60 | default: break; 61 | } 62 | return NULL; 63 | } 64 | */ 65 | 66 | func flag_table_3_3_location(sec [][]unsigned_char) []unsigned_char { 67 | var grid_template, center int 68 | var gds []unsigned_char 69 | 70 | grid_template = code_table_3_1(sec) 71 | center = GB2_Center(sec) 72 | gds = sec[3] 73 | switch grid_template { 74 | case 0, 1, 2, 3, 40, 41, 42, 43, 140, 204: 75 | return gds[54:] 76 | case 4, 5, 10, 12, 20, 30, 31, 90, 110: 77 | return gds[46:] 78 | case 32768: 79 | if center == NCEP { 80 | return gds[54:] 81 | } 82 | return nil 83 | case 32769: 84 | if center == NCEP { 85 | return gds[54:] 86 | } 87 | return nil 88 | case 40110: 89 | if (center == JMA1) || (center == JMA2) { 90 | return gds[46:] 91 | } 92 | return nil 93 | default: 94 | } 95 | return nil 96 | } 97 | 98 | /* 99 | int flag_table_3_4(unsigned char **sec) { 100 | unsigned char *p; 101 | p = flag_table_3_4_location(sec); 102 | if (p == NULL) return -1; 103 | return (int) *p; 104 | } 105 | */ 106 | func flag_table_3_4(sec [][]unsigned_char) int { 107 | var p []unsigned_char 108 | p = flag_table_3_4_location(sec) 109 | if p == nil { 110 | return -1 111 | } 112 | return int(p[0]) 113 | } 114 | 115 | /* 116 | 117 | unsigned char *flag_table_3_4_location(unsigned char **sec) { 118 | int grid_template, center; 119 | unsigned char *gds; 120 | 121 | gds = sec[3]; 122 | grid_template = code_table_3_1(sec); 123 | center = GB2_Center(sec); 124 | 125 | switch (grid_template) { 126 | case 0: 127 | case 1: 128 | case 2: 129 | case 3: 130 | case 40: 131 | case 41: 132 | case 42: 133 | case 43: 134 | return gds+71; break; 135 | case 4: 136 | case 5: 137 | return gds+47; break; 138 | case 10: 139 | case 12: 140 | return gds+59; break; 141 | case 20: return gds+64; break; 142 | case 30: 143 | case 31: return gds+64; break; 144 | case 50: 145 | case 51: 146 | case 52: 147 | case 53: 148 | /* spectral modes don't have scan order / 149 | return NULL; break; 150 | case 90: 151 | case 140: 152 | return gds+63; break; 153 | case 110: return gds+56; break; 154 | case 190: 155 | case 120: return gds+38; break; 156 | case 204: return gds+71; break; 157 | case 1000: return gds+50; break; 158 | case 32768: 159 | if (center == NCEP) return gds+71; 160 | return NULL; 161 | break; 162 | case 32769: 163 | if (center == NCEP) return gds+71; 164 | return NULL; 165 | break; 166 | case 40110: 167 | if ((center == JMA1) || (center == JMA2)) return gds+56; 168 | return NULL; 169 | break; 170 | default: break; 171 | } 172 | return NULL; 173 | } 174 | */ 175 | 176 | func flag_table_3_4_location(sec [][]unsigned_char) []unsigned_char { 177 | var grid_template, center int 178 | var gds []unsigned_char 179 | 180 | gds = sec[3] 181 | grid_template = code_table_3_1(sec) 182 | center = GB2_Center(sec) 183 | 184 | switch grid_template { 185 | case 0, 1, 2, 3, 40, 41, 42, 43: 186 | return gds[71:] 187 | case 4, 5: 188 | return gds[47:] 189 | case 10, 12: 190 | return gds[59:] 191 | case 20: 192 | return gds[64:] 193 | case 30, 31: 194 | return gds[64:] 195 | case 50, 51, 52, 53: 196 | /* spectral modes don't have scan order */ 197 | return nil 198 | case 90, 140: 199 | return gds[63:] 200 | case 110: 201 | return gds[56:] 202 | case 190, 120: 203 | return gds[38:] 204 | case 204: 205 | return gds[71:] 206 | case 1000: 207 | return gds[50:] 208 | case 32768: 209 | if center == NCEP { 210 | return gds[71:] 211 | } 212 | return nil 213 | case 32769: 214 | if center == NCEP { 215 | return gds[71:] 216 | } 217 | return nil 218 | case 40110: 219 | if (center == JMA1) || (center == JMA2) { 220 | return gds[56:] 221 | } 222 | return nil 223 | default: 224 | } 225 | return nil 226 | } 227 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/errors_test.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "reflect" 8 | "testing" 9 | ) 10 | 11 | func TestNew(t *testing.T) { 12 | tests := []struct { 13 | err string 14 | want error 15 | }{ 16 | {"", fmt.Errorf("")}, 17 | {"foo", fmt.Errorf("foo")}, 18 | {"foo", New("foo")}, 19 | {"string with format specifiers: %v", errors.New("string with format specifiers: %v")}, 20 | } 21 | 22 | for _, tt := range tests { 23 | got := New(tt.err) 24 | if got.Error() != tt.want.Error() { 25 | t.Errorf("New.Error(): got: %q, want %q", got, tt.want) 26 | } 27 | } 28 | } 29 | 30 | func TestWrapNil(t *testing.T) { 31 | got := Wrap(nil, "no error") 32 | if got != nil { 33 | t.Errorf("Wrap(nil, \"no error\"): got %#v, expected nil", got) 34 | } 35 | } 36 | 37 | func TestWrap(t *testing.T) { 38 | tests := []struct { 39 | err error 40 | message string 41 | want string 42 | }{ 43 | {io.EOF, "read error", "read error: EOF"}, 44 | {Wrap(io.EOF, "read error"), "client error", "client error: read error: EOF"}, 45 | } 46 | 47 | for _, tt := range tests { 48 | got := Wrap(tt.err, tt.message).Error() 49 | if got != tt.want { 50 | t.Errorf("Wrap(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) 51 | } 52 | } 53 | } 54 | 55 | type nilError struct{} 56 | 57 | func (nilError) Error() string { return "nil error" } 58 | 59 | func TestCause(t *testing.T) { 60 | x := New("error") 61 | tests := []struct { 62 | err error 63 | want error 64 | }{{ 65 | // nil error is nil 66 | err: nil, 67 | want: nil, 68 | }, { 69 | // explicit nil error is nil 70 | err: (error)(nil), 71 | want: nil, 72 | }, { 73 | // typed nil is nil 74 | err: (*nilError)(nil), 75 | want: (*nilError)(nil), 76 | }, { 77 | // uncaused error is unaffected 78 | err: io.EOF, 79 | want: io.EOF, 80 | }, { 81 | // caused error returns cause 82 | err: Wrap(io.EOF, "ignored"), 83 | want: io.EOF, 84 | }, { 85 | err: x, // return from errors.New 86 | want: x, 87 | }, { 88 | WithMessage(nil, "whoops"), 89 | nil, 90 | }, { 91 | WithMessage(io.EOF, "whoops"), 92 | io.EOF, 93 | }, { 94 | WithStack(nil), 95 | nil, 96 | }, { 97 | WithStack(io.EOF), 98 | io.EOF, 99 | }} 100 | 101 | for i, tt := range tests { 102 | got := Cause(tt.err) 103 | if !reflect.DeepEqual(got, tt.want) { 104 | t.Errorf("test %d: got %#v, want %#v", i+1, got, tt.want) 105 | } 106 | } 107 | } 108 | 109 | func TestWrapfNil(t *testing.T) { 110 | got := Wrapf(nil, "no error") 111 | if got != nil { 112 | t.Errorf("Wrapf(nil, \"no error\"): got %#v, expected nil", got) 113 | } 114 | } 115 | 116 | func TestWrapf(t *testing.T) { 117 | tests := []struct { 118 | err error 119 | message string 120 | want string 121 | }{ 122 | {io.EOF, "read error", "read error: EOF"}, 123 | {Wrapf(io.EOF, "read error without format specifiers"), "client error", "client error: read error without format specifiers: EOF"}, 124 | {Wrapf(io.EOF, "read error with %d format specifier", 1), "client error", "client error: read error with 1 format specifier: EOF"}, 125 | } 126 | 127 | for _, tt := range tests { 128 | got := Wrapf(tt.err, tt.message).Error() 129 | if got != tt.want { 130 | t.Errorf("Wrapf(%v, %q): got: %v, want %v", tt.err, tt.message, got, tt.want) 131 | } 132 | } 133 | } 134 | 135 | func TestErrorf(t *testing.T) { 136 | tests := []struct { 137 | err error 138 | want string 139 | }{ 140 | {Errorf("read error without format specifiers"), "read error without format specifiers"}, 141 | {Errorf("read error with %d format specifier", 1), "read error with 1 format specifier"}, 142 | } 143 | 144 | for _, tt := range tests { 145 | got := tt.err.Error() 146 | if got != tt.want { 147 | t.Errorf("Errorf(%v): got: %q, want %q", tt.err, got, tt.want) 148 | } 149 | } 150 | } 151 | 152 | func TestWithStackNil(t *testing.T) { 153 | got := WithStack(nil) 154 | if got != nil { 155 | t.Errorf("WithStack(nil): got %#v, expected nil", got) 156 | } 157 | } 158 | 159 | func TestWithStack(t *testing.T) { 160 | tests := []struct { 161 | err error 162 | want string 163 | }{ 164 | {io.EOF, "EOF"}, 165 | {WithStack(io.EOF), "EOF"}, 166 | } 167 | 168 | for _, tt := range tests { 169 | got := WithStack(tt.err).Error() 170 | if got != tt.want { 171 | t.Errorf("WithStack(%v): got: %v, want %v", tt.err, got, tt.want) 172 | } 173 | } 174 | } 175 | 176 | func TestWithMessageNil(t *testing.T) { 177 | got := WithMessage(nil, "no error") 178 | if got != nil { 179 | t.Errorf("WithMessage(nil, \"no error\"): got %#v, expected nil", got) 180 | } 181 | } 182 | 183 | func TestWithMessage(t *testing.T) { 184 | tests := []struct { 185 | err error 186 | message string 187 | want string 188 | }{ 189 | {io.EOF, "read error", "read error: EOF"}, 190 | {WithMessage(io.EOF, "read error"), "client error", "client error: read error: EOF"}, 191 | } 192 | 193 | for _, tt := range tests { 194 | got := WithMessage(tt.err, tt.message).Error() 195 | if got != tt.want { 196 | t.Errorf("WithMessage(%v, %q): got: %q, want %q", tt.err, tt.message, got, tt.want) 197 | } 198 | } 199 | 200 | } 201 | 202 | // errors.New, etc values are not expected to be compared by value 203 | // but the change in errors#27 made them incomparable. Assert that 204 | // various kinds of errors have a functional equality operator, even 205 | // if the result of that equality is always false. 206 | func TestErrorEquality(t *testing.T) { 207 | vals := []error{ 208 | nil, 209 | io.EOF, 210 | errors.New("EOF"), 211 | New("EOF"), 212 | Errorf("EOF"), 213 | Wrap(io.EOF, "EOF"), 214 | Wrapf(io.EOF, "EOF%d", 2), 215 | WithMessage(nil, "whoops"), 216 | WithMessage(io.EOF, "whoops"), 217 | WithStack(io.EOF), 218 | WithStack(nil), 219 | } 220 | 221 | for i := range vals { 222 | for j := range vals { 223 | _ = vals[i] == vals[j] // mustn't panic 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/example_test.go: -------------------------------------------------------------------------------- 1 | package errors_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/pkg/errors" 7 | ) 8 | 9 | func ExampleNew() { 10 | err := errors.New("whoops") 11 | fmt.Println(err) 12 | 13 | // Output: whoops 14 | } 15 | 16 | func ExampleNew_printf() { 17 | err := errors.New("whoops") 18 | fmt.Printf("%+v", err) 19 | 20 | // Example output: 21 | // whoops 22 | // github.com/pkg/errors_test.ExampleNew_printf 23 | // /home/dfc/src/github.com/pkg/errors/example_test.go:17 24 | // testing.runExample 25 | // /home/dfc/go/src/testing/example.go:114 26 | // testing.RunExamples 27 | // /home/dfc/go/src/testing/example.go:38 28 | // testing.(*M).Run 29 | // /home/dfc/go/src/testing/testing.go:744 30 | // main.main 31 | // /github.com/pkg/errors/_test/_testmain.go:106 32 | // runtime.main 33 | // /home/dfc/go/src/runtime/proc.go:183 34 | // runtime.goexit 35 | // /home/dfc/go/src/runtime/asm_amd64.s:2059 36 | } 37 | 38 | func ExampleWithMessage() { 39 | cause := errors.New("whoops") 40 | err := errors.WithMessage(cause, "oh noes") 41 | fmt.Println(err) 42 | 43 | // Output: oh noes: whoops 44 | } 45 | 46 | func ExampleWithStack() { 47 | cause := errors.New("whoops") 48 | err := errors.WithStack(cause) 49 | fmt.Println(err) 50 | 51 | // Output: whoops 52 | } 53 | 54 | func ExampleWithStack_printf() { 55 | cause := errors.New("whoops") 56 | err := errors.WithStack(cause) 57 | fmt.Printf("%+v", err) 58 | 59 | // Example Output: 60 | // whoops 61 | // github.com/pkg/errors_test.ExampleWithStack_printf 62 | // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55 63 | // testing.runExample 64 | // /usr/lib/go/src/testing/example.go:114 65 | // testing.RunExamples 66 | // /usr/lib/go/src/testing/example.go:38 67 | // testing.(*M).Run 68 | // /usr/lib/go/src/testing/testing.go:744 69 | // main.main 70 | // github.com/pkg/errors/_test/_testmain.go:106 71 | // runtime.main 72 | // /usr/lib/go/src/runtime/proc.go:183 73 | // runtime.goexit 74 | // /usr/lib/go/src/runtime/asm_amd64.s:2086 75 | // github.com/pkg/errors_test.ExampleWithStack_printf 76 | // /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56 77 | // testing.runExample 78 | // /usr/lib/go/src/testing/example.go:114 79 | // testing.RunExamples 80 | // /usr/lib/go/src/testing/example.go:38 81 | // testing.(*M).Run 82 | // /usr/lib/go/src/testing/testing.go:744 83 | // main.main 84 | // github.com/pkg/errors/_test/_testmain.go:106 85 | // runtime.main 86 | // /usr/lib/go/src/runtime/proc.go:183 87 | // runtime.goexit 88 | // /usr/lib/go/src/runtime/asm_amd64.s:2086 89 | } 90 | 91 | func ExampleWrap() { 92 | cause := errors.New("whoops") 93 | err := errors.Wrap(cause, "oh noes") 94 | fmt.Println(err) 95 | 96 | // Output: oh noes: whoops 97 | } 98 | 99 | func fn() error { 100 | e1 := errors.New("error") 101 | e2 := errors.Wrap(e1, "inner") 102 | e3 := errors.Wrap(e2, "middle") 103 | return errors.Wrap(e3, "outer") 104 | } 105 | 106 | func ExampleCause() { 107 | err := fn() 108 | fmt.Println(err) 109 | fmt.Println(errors.Cause(err)) 110 | 111 | // Output: outer: middle: inner: error 112 | // error 113 | } 114 | 115 | func ExampleWrap_extended() { 116 | err := fn() 117 | fmt.Printf("%+v\n", err) 118 | 119 | // Example output: 120 | // error 121 | // github.com/pkg/errors_test.fn 122 | // /home/dfc/src/github.com/pkg/errors/example_test.go:47 123 | // github.com/pkg/errors_test.ExampleCause_printf 124 | // /home/dfc/src/github.com/pkg/errors/example_test.go:63 125 | // testing.runExample 126 | // /home/dfc/go/src/testing/example.go:114 127 | // testing.RunExamples 128 | // /home/dfc/go/src/testing/example.go:38 129 | // testing.(*M).Run 130 | // /home/dfc/go/src/testing/testing.go:744 131 | // main.main 132 | // /github.com/pkg/errors/_test/_testmain.go:104 133 | // runtime.main 134 | // /home/dfc/go/src/runtime/proc.go:183 135 | // runtime.goexit 136 | // /home/dfc/go/src/runtime/asm_amd64.s:2059 137 | // github.com/pkg/errors_test.fn 138 | // /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner 139 | // github.com/pkg/errors_test.fn 140 | // /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle 141 | // github.com/pkg/errors_test.fn 142 | // /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer 143 | } 144 | 145 | func ExampleWrapf() { 146 | cause := errors.New("whoops") 147 | err := errors.Wrapf(cause, "oh noes #%d", 2) 148 | fmt.Println(err) 149 | 150 | // Output: oh noes #2: whoops 151 | } 152 | 153 | func ExampleErrorf_extended() { 154 | err := errors.Errorf("whoops: %s", "foo") 155 | fmt.Printf("%+v", err) 156 | 157 | // Example output: 158 | // whoops: foo 159 | // github.com/pkg/errors_test.ExampleErrorf 160 | // /home/dfc/src/github.com/pkg/errors/example_test.go:101 161 | // testing.runExample 162 | // /home/dfc/go/src/testing/example.go:114 163 | // testing.RunExamples 164 | // /home/dfc/go/src/testing/example.go:38 165 | // testing.(*M).Run 166 | // /home/dfc/go/src/testing/testing.go:744 167 | // main.main 168 | // /github.com/pkg/errors/_test/_testmain.go:102 169 | // runtime.main 170 | // /home/dfc/go/src/runtime/proc.go:183 171 | // runtime.goexit 172 | // /home/dfc/go/src/runtime/asm_amd64.s:2059 173 | } 174 | 175 | func Example_stackTrace() { 176 | type stackTracer interface { 177 | StackTrace() errors.StackTrace 178 | } 179 | 180 | err, ok := errors.Cause(fn()).(stackTracer) 181 | if !ok { 182 | panic("oops, err does not implement stackTracer") 183 | } 184 | 185 | st := err.StackTrace() 186 | fmt.Printf("%+v", st[0:2]) // top two frames 187 | 188 | // Example output: 189 | // github.com/pkg/errors_test.fn 190 | // /home/dfc/src/github.com/pkg/errors/example_test.go:47 191 | // github.com/pkg/errors_test.Example_stackTrace 192 | // /home/dfc/src/github.com/pkg/errors/example_test.go:127 193 | } 194 | 195 | func ExampleCause_printf() { 196 | err := errors.Wrap(func() error { 197 | return func() error { 198 | return errors.Errorf("hello %s", fmt.Sprintf("world")) 199 | }() 200 | }(), "failed") 201 | 202 | fmt.Printf("%v", err) 203 | 204 | // Output: failed: hello world 205 | } 206 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/stack_test.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "testing" 7 | ) 8 | 9 | var initpc, _, _, _ = runtime.Caller(0) 10 | 11 | func TestFrameLine(t *testing.T) { 12 | var tests = []struct { 13 | Frame 14 | want int 15 | }{{ 16 | Frame(initpc), 17 | 9, 18 | }, { 19 | func() Frame { 20 | var pc, _, _, _ = runtime.Caller(0) 21 | return Frame(pc) 22 | }(), 23 | 20, 24 | }, { 25 | func() Frame { 26 | var pc, _, _, _ = runtime.Caller(1) 27 | return Frame(pc) 28 | }(), 29 | 28, 30 | }, { 31 | Frame(0), // invalid PC 32 | 0, 33 | }} 34 | 35 | for _, tt := range tests { 36 | got := tt.Frame.line() 37 | want := tt.want 38 | if want != got { 39 | t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got) 40 | } 41 | } 42 | } 43 | 44 | type X struct{} 45 | 46 | func (x X) val() Frame { 47 | var pc, _, _, _ = runtime.Caller(0) 48 | return Frame(pc) 49 | } 50 | 51 | func (x *X) ptr() Frame { 52 | var pc, _, _, _ = runtime.Caller(0) 53 | return Frame(pc) 54 | } 55 | 56 | func TestFrameFormat(t *testing.T) { 57 | var tests = []struct { 58 | Frame 59 | format string 60 | want string 61 | }{{ 62 | Frame(initpc), 63 | "%s", 64 | "stack_test.go", 65 | }, { 66 | Frame(initpc), 67 | "%+s", 68 | "github.com/pkg/errors.init\n" + 69 | "\t.+/github.com/pkg/errors/stack_test.go", 70 | }, { 71 | Frame(0), 72 | "%s", 73 | "unknown", 74 | }, { 75 | Frame(0), 76 | "%+s", 77 | "unknown", 78 | }, { 79 | Frame(initpc), 80 | "%d", 81 | "9", 82 | }, { 83 | Frame(0), 84 | "%d", 85 | "0", 86 | }, { 87 | Frame(initpc), 88 | "%n", 89 | "init", 90 | }, { 91 | func() Frame { 92 | var x X 93 | return x.ptr() 94 | }(), 95 | "%n", 96 | `\(\*X\).ptr`, 97 | }, { 98 | func() Frame { 99 | var x X 100 | return x.val() 101 | }(), 102 | "%n", 103 | "X.val", 104 | }, { 105 | Frame(0), 106 | "%n", 107 | "", 108 | }, { 109 | Frame(initpc), 110 | "%v", 111 | "stack_test.go:9", 112 | }, { 113 | Frame(initpc), 114 | "%+v", 115 | "github.com/pkg/errors.init\n" + 116 | "\t.+/github.com/pkg/errors/stack_test.go:9", 117 | }, { 118 | Frame(0), 119 | "%v", 120 | "unknown:0", 121 | }} 122 | 123 | for i, tt := range tests { 124 | testFormatRegexp(t, i, tt.Frame, tt.format, tt.want) 125 | } 126 | } 127 | 128 | func TestFuncname(t *testing.T) { 129 | tests := []struct { 130 | name, want string 131 | }{ 132 | {"", ""}, 133 | {"runtime.main", "main"}, 134 | {"github.com/pkg/errors.funcname", "funcname"}, 135 | {"funcname", "funcname"}, 136 | {"io.copyBuffer", "copyBuffer"}, 137 | {"main.(*R).Write", "(*R).Write"}, 138 | } 139 | 140 | for _, tt := range tests { 141 | got := funcname(tt.name) 142 | want := tt.want 143 | if got != want { 144 | t.Errorf("funcname(%q): want: %q, got %q", tt.name, want, got) 145 | } 146 | } 147 | } 148 | 149 | func TestTrimGOPATH(t *testing.T) { 150 | var tests = []struct { 151 | Frame 152 | want string 153 | }{{ 154 | Frame(initpc), 155 | "github.com/pkg/errors/stack_test.go", 156 | }} 157 | 158 | for i, tt := range tests { 159 | pc := tt.Frame.pc() 160 | fn := runtime.FuncForPC(pc) 161 | file, _ := fn.FileLine(pc) 162 | got := trimGOPATH(fn.Name(), file) 163 | testFormatRegexp(t, i, got, "%s", tt.want) 164 | } 165 | } 166 | 167 | func TestStackTrace(t *testing.T) { 168 | tests := []struct { 169 | err error 170 | want []string 171 | }{{ 172 | New("ooh"), []string{ 173 | "github.com/pkg/errors.TestStackTrace\n" + 174 | "\t.+/github.com/pkg/errors/stack_test.go:172", 175 | }, 176 | }, { 177 | Wrap(New("ooh"), "ahh"), []string{ 178 | "github.com/pkg/errors.TestStackTrace\n" + 179 | "\t.+/github.com/pkg/errors/stack_test.go:177", // this is the stack of Wrap, not New 180 | }, 181 | }, { 182 | Cause(Wrap(New("ooh"), "ahh")), []string{ 183 | "github.com/pkg/errors.TestStackTrace\n" + 184 | "\t.+/github.com/pkg/errors/stack_test.go:182", // this is the stack of New 185 | }, 186 | }, { 187 | func() error { return New("ooh") }(), []string{ 188 | `github.com/pkg/errors.(func·009|TestStackTrace.func1)` + 189 | "\n\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New 190 | "github.com/pkg/errors.TestStackTrace\n" + 191 | "\t.+/github.com/pkg/errors/stack_test.go:187", // this is the stack of New's caller 192 | }, 193 | }, { 194 | Cause(func() error { 195 | return func() error { 196 | return Errorf("hello %s", fmt.Sprintf("world")) 197 | }() 198 | }()), []string{ 199 | `github.com/pkg/errors.(func·010|TestStackTrace.func2.1)` + 200 | "\n\t.+/github.com/pkg/errors/stack_test.go:196", // this is the stack of Errorf 201 | `github.com/pkg/errors.(func·011|TestStackTrace.func2)` + 202 | "\n\t.+/github.com/pkg/errors/stack_test.go:197", // this is the stack of Errorf's caller 203 | "github.com/pkg/errors.TestStackTrace\n" + 204 | "\t.+/github.com/pkg/errors/stack_test.go:198", // this is the stack of Errorf's caller's caller 205 | }, 206 | }} 207 | for i, tt := range tests { 208 | x, ok := tt.err.(interface { 209 | StackTrace() StackTrace 210 | }) 211 | if !ok { 212 | t.Errorf("expected %#v to implement StackTrace() StackTrace", tt.err) 213 | continue 214 | } 215 | st := x.StackTrace() 216 | for j, want := range tt.want { 217 | testFormatRegexp(t, i, st[j], "%+v", want) 218 | } 219 | } 220 | } 221 | 222 | func stackTrace() StackTrace { 223 | const depth = 8 224 | var pcs [depth]uintptr 225 | n := runtime.Callers(1, pcs[:]) 226 | var st stack = pcs[0:n] 227 | return st.StackTrace() 228 | } 229 | 230 | func TestStackTraceFormat(t *testing.T) { 231 | tests := []struct { 232 | StackTrace 233 | format string 234 | want string 235 | }{{ 236 | nil, 237 | "%s", 238 | `\[\]`, 239 | }, { 240 | nil, 241 | "%v", 242 | `\[\]`, 243 | }, { 244 | nil, 245 | "%+v", 246 | "", 247 | }, { 248 | nil, 249 | "%#v", 250 | `\[\]errors.Frame\(nil\)`, 251 | }, { 252 | make(StackTrace, 0), 253 | "%s", 254 | `\[\]`, 255 | }, { 256 | make(StackTrace, 0), 257 | "%v", 258 | `\[\]`, 259 | }, { 260 | make(StackTrace, 0), 261 | "%+v", 262 | "", 263 | }, { 264 | make(StackTrace, 0), 265 | "%#v", 266 | `\[\]errors.Frame{}`, 267 | }, { 268 | stackTrace()[:2], 269 | "%s", 270 | `\[stack_test.go stack_test.go\]`, 271 | }, { 272 | stackTrace()[:2], 273 | "%v", 274 | `\[stack_test.go:225 stack_test.go:272\]`, 275 | }, { 276 | stackTrace()[:2], 277 | "%+v", 278 | "\n" + 279 | "github.com/pkg/errors.stackTrace\n" + 280 | "\t.+/github.com/pkg/errors/stack_test.go:225\n" + 281 | "github.com/pkg/errors.TestStackTraceFormat\n" + 282 | "\t.+/github.com/pkg/errors/stack_test.go:276", 283 | }, { 284 | stackTrace()[:2], 285 | "%#v", 286 | `\[\]errors.Frame{stack_test.go:225, stack_test.go:284}`, 287 | }} 288 | 289 | for i, tt := range tests { 290 | testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want) 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /internal/unpk_0.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 1996 wesley ebisuzaki 4 | * 5 | * Unpack BDS section 6 | * 7 | * input: *bits, pointer to packed integer data 8 | * *bitmap, pointer to bitmap (undefined data), NULL if none 9 | * n_bits, number of bits per packed integer 10 | * n, number of data points (includes undefined data) 11 | * ref, scale: flt[] = ref + scale*packed_int 12 | * output: *flt, pointer to output array 13 | * undefined values filled with UNDEFINED 14 | * 15 | * note: code assumes an integer >= 32 bits 16 | * 17 | * 7/98 v1.2.1 fix bug for bitmaps and nbit >= 25 found by Larry Brasfield 18 | * 2/01 v1.2.2 changed jj from long int to double 19 | * 3/02 v1.2.3 added unpacking extensions for spectral data 20 | * Luis Kornblueh, MPIfM 21 | * 7/06 v.1.2.4 fixed some bug complex packed data was not set to undefined 22 | * 10/15 v.1.2.5 changed n and i to unsigned 23 | * 3/16 v.1.2.6 OpenMP 24 | * 6/16 v.1.2.7 faster OpenMP and optimization 25 | */ 26 | 27 | var mask = []int{0, 1, 3, 7, 15, 31, 63, 127, 255} 28 | var shift = []double{1.0, 2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0} 29 | 30 | /* 31 | void unpk_0(float *flt, unsigned char *bits0, unsigned char *bitmap0, 32 | int n_bits, unsigned int n, double ref, double scale, double dec_scale) { 33 | 34 | unsigned char *bits, *bitmap; 35 | 36 | int c_bits, j_bits, nthreads; 37 | unsigned int map_mask, bbits, i, j, k, n_missing, ndef, di; 38 | double jj; 39 | 40 | ref = ref * dec_scale; 41 | scale = scale * dec_scale; 42 | bits = bits0; 43 | bitmap = bitmap0; 44 | 45 | bbits = 0; 46 | 47 | /* assume integer has 32+ bits */ 48 | /* optimized code for n_bits <= 25bits / 49 | if (n_bits <= 25) { 50 | n_missing = bitmap ? missing_points(bitmap0, n) : 0; 51 | ndef = n - n_missing; 52 | 53 | // 1-cpu: rd_bitstream_flt(bits0, 0, flt+n_missing, n_bits, ndef); 54 | // 1-cpu: for (j = 0; j < ndef; j++) flt[j+n_missing] = ref + scale*flt[j+n_missing]; 55 | 56 | #pragma omp parallel private(i,j,k) 57 | { 58 | #pragma omp single 59 | { 60 | nthreads = omp_get_num_threads(); 61 | di = (ndef + nthreads - 1) / nthreads; 62 | di = ((di + 7) | 7) ^ 7; 63 | } 64 | #pragma omp for 65 | for (i = 0; i < ndef; i += di) { 66 | k = ndef - i; 67 | if (k > di) k = di; 68 | rd_bitstream_flt(bits0 + (i/8)*n_bits, 0, flt+n_missing+i, n_bits, k); 69 | for (j = i+n_missing; j < i+k+n_missing; j++) { 70 | flt[j] = ref + scale*flt[j]; 71 | } 72 | } 73 | } 74 | /* 75 | #pragma omp parallel for private(i,j,k) 76 | for (i = 0; i < ndef; i += CACHE_LINE_BITS) { 77 | k = ndef - i; 78 | if (k > CACHE_LINE_BITS) k = CACHE_LINE_BITS; 79 | rd_bitstream_flt(bits0 + (i/8)*n_bits, 0, flt+n_missing+i, n_bits, k); 80 | for (j = i+n_missing; j < i+k+n_missing; j++) { 81 | flt[j] = ref + scale*flt[j]; 82 | } 83 | } 84 | / 85 | 86 | if (n_missing != 0) { 87 | j = n_missing; 88 | for (i = 0; i < n; i++) { 89 | /* check bitmap / 90 | if ((i & 7) == 0) bbits = *bitmap++; 91 | if (bbits & 128) { 92 | flt[i] = flt[j++]; 93 | } 94 | else { 95 | flt[i] = UNDEFINED; 96 | } 97 | bbits = bbits << 1; 98 | } 99 | } 100 | } 101 | else { 102 | /* older unoptimized code, not often used / 103 | c_bits = 8; 104 | map_mask = 128; 105 | while (n-- > 0) { 106 | if (bitmap) { 107 | j = (*bitmap & map_mask); 108 | if ((map_mask >>= 1) == 0) { 109 | map_mask = 128; 110 | bitmap++; 111 | } 112 | if (j == 0) { 113 | *flt++ = UNDEFINED; 114 | continue; 115 | } 116 | } 117 | 118 | jj = 0.0; 119 | j_bits = n_bits; 120 | while (c_bits <= j_bits) { 121 | if (c_bits == 8) { 122 | jj = jj * 256.0 + (double) (*bits++); 123 | j_bits -= 8; 124 | } 125 | else { 126 | jj = (jj * shift[c_bits]) + (double) (*bits & mask[c_bits]); 127 | bits++; 128 | j_bits -= c_bits; 129 | c_bits = 8; 130 | } 131 | } 132 | if (j_bits) { 133 | c_bits -= j_bits; 134 | jj = (jj * shift[j_bits]) + (double) ((*bits >> c_bits) & mask[j_bits]); 135 | } 136 | *flt++ = ref + scale*jj; 137 | } 138 | } 139 | return; 140 | } 141 | */ 142 | 143 | func unpk_0(flt []float, bits0 []unsigned_char, bitmap0 []unsigned_char, n_bits int, n unsigned_int, ref double, scale double, dec_scale double) error { 144 | 145 | var bits, bitmap []unsigned_char 146 | 147 | var c_bits, j_bits, nthreads int 148 | var map_mask, bbits, i, j, k, n_missing, ndef, di unsigned_int 149 | var jj double 150 | 151 | ref = ref * dec_scale 152 | scale = scale * dec_scale 153 | //bits = bits0 154 | bitmap = bitmap0 155 | 156 | bbits = 0 157 | 158 | /* assume integer has 32+ bits */ 159 | /* optimized code for n_bits <= 25bits */ 160 | if n_bits <= 25 { 161 | // n_missing = bitmap ? missing_points(bitmap0, n) : 0; 162 | if bitmap != nil { 163 | n_missing = missing_points(bitmap0, n) 164 | } else { 165 | n_missing = 0 166 | } 167 | ndef = n - n_missing 168 | 169 | // 1-cpu: rd_bitstream_flt(bits0, 0, flt+n_missing, n_bits, ndef); 170 | // 1-cpu: for (j = 0; j < ndef; j++) flt[j+n_missing] = ref + scale*flt[j+n_missing]; 171 | 172 | //#pragma omp parallel private(i,j,k) 173 | { 174 | //#pragma omp single 175 | { 176 | nthreads = 1 //omp_get_num_threads(); 177 | di = (ndef + unsigned_int(nthreads) - 1) / unsigned_int(nthreads) 178 | di = ((di + 7) | 7) ^ 7 179 | } 180 | //#pragma omp for 181 | for i = 0; i < ndef; i += di { 182 | k = ndef - i 183 | if k > di { 184 | k = di 185 | } 186 | err := rd_bitstream_flt(bits0[int(i/8)*n_bits:], 0, flt[n_missing+i:], n_bits, int(k)) 187 | if err != nil { 188 | return fatal_error_wrap(err, "Failed to execute rd_bitstream_flt") 189 | } 190 | for j = i + n_missing; j < i+k+n_missing; j++ { 191 | flt[j] = float(ref + scale*double(flt[j])) 192 | } 193 | } 194 | } 195 | /* 196 | #pragma omp parallel for private(i,j,k) 197 | for (i = 0; i < ndef; i += CACHE_LINE_BITS) { 198 | k = ndef - i; 199 | if (k > CACHE_LINE_BITS) k = CACHE_LINE_BITS; 200 | rd_bitstream_flt(bits0 + (i/8)*n_bits, 0, flt+n_missing+i, n_bits, k); 201 | for (j = i+n_missing; j < i+k+n_missing; j++) { 202 | flt[j] = ref + scale*flt[j]; 203 | } 204 | } 205 | */ 206 | 207 | if n_missing != 0 { 208 | j = n_missing 209 | bitmap_index := 0 210 | for i = 0; i < n; i++ { 211 | /* check bitmap */ 212 | if (i & 7) == 0 { 213 | bbits = unsigned_int(bitmap[bitmap_index]) 214 | bitmap_index++ 215 | } 216 | if (bbits & 128) != 0 { 217 | flt[i] = flt[j] 218 | j++ 219 | } else { 220 | flt[i] = UNDEFINED 221 | } 222 | bbits = bbits << 1 223 | } 224 | } 225 | } else { 226 | /* older unoptimized code, not often used */ 227 | c_bits = 8 228 | map_mask = 128 229 | flt_index := 0 230 | bitmap_index := 0 231 | bits_index := 0 232 | for n > 0 { 233 | n-- 234 | if bitmap != nil { 235 | j = unsigned_int(bitmap[bitmap_index]) & map_mask 236 | //if ((map_mask >>= 1) == 0) { 237 | map_mask = map_mask >> 1 238 | if map_mask == 0 { 239 | map_mask = 128 240 | bitmap_index++ 241 | } 242 | if j == 0 { 243 | flt[flt_index] = UNDEFINED 244 | flt_index++ 245 | continue 246 | } 247 | } 248 | 249 | jj = 0.0 250 | j_bits = n_bits 251 | for c_bits <= j_bits { 252 | if c_bits == 8 { 253 | jj = jj*256.0 + double(bits[bits_index]) 254 | bits_index++ 255 | j_bits -= 8 256 | } else { 257 | jj = (jj * shift[c_bits]) + double(int(bits[bits_index])&mask[c_bits]) 258 | bits_index++ 259 | j_bits -= c_bits 260 | c_bits = 8 261 | } 262 | } 263 | if j_bits != 0 { 264 | c_bits -= j_bits 265 | jj = (jj * shift[j_bits]) + double((int(bits[bits_index])>>unsigned_int(c_bits))&mask[j_bits]) 266 | } 267 | flt[flt_index] = float(ref + scale*jj) 268 | flt_index++ 269 | } 270 | } 271 | return nil 272 | } 273 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/errors.go: -------------------------------------------------------------------------------- 1 | // Package errors provides simple error handling primitives. 2 | // 3 | // The traditional error handling idiom in Go is roughly akin to 4 | // 5 | // if err != nil { 6 | // return err 7 | // } 8 | // 9 | // which applied recursively up the call stack results in error reports 10 | // without context or debugging information. The errors package allows 11 | // programmers to add context to the failure path in their code in a way 12 | // that does not destroy the original value of the error. 13 | // 14 | // Adding context to an error 15 | // 16 | // The errors.Wrap function returns a new error that adds context to the 17 | // original error by recording a stack trace at the point Wrap is called, 18 | // and the supplied message. For example 19 | // 20 | // _, err := ioutil.ReadAll(r) 21 | // if err != nil { 22 | // return errors.Wrap(err, "read failed") 23 | // } 24 | // 25 | // If additional control is required the errors.WithStack and errors.WithMessage 26 | // functions destructure errors.Wrap into its component operations of annotating 27 | // an error with a stack trace and an a message, respectively. 28 | // 29 | // Retrieving the cause of an error 30 | // 31 | // Using errors.Wrap constructs a stack of errors, adding context to the 32 | // preceding error. Depending on the nature of the error it may be necessary 33 | // to reverse the operation of errors.Wrap to retrieve the original error 34 | // for inspection. Any error value which implements this interface 35 | // 36 | // type causer interface { 37 | // Cause() error 38 | // } 39 | // 40 | // can be inspected by errors.Cause. errors.Cause will recursively retrieve 41 | // the topmost error which does not implement causer, which is assumed to be 42 | // the original cause. For example: 43 | // 44 | // switch err := errors.Cause(err).(type) { 45 | // case *MyError: 46 | // // handle specifically 47 | // default: 48 | // // unknown error 49 | // } 50 | // 51 | // causer interface is not exported by this package, but is considered a part 52 | // of stable public API. 53 | // 54 | // Formatted printing of errors 55 | // 56 | // All error values returned from this package implement fmt.Formatter and can 57 | // be formatted by the fmt package. The following verbs are supported 58 | // 59 | // %s print the error. If the error has a Cause it will be 60 | // printed recursively 61 | // %v see %s 62 | // %+v extended format. Each Frame of the error's StackTrace will 63 | // be printed in detail. 64 | // 65 | // Retrieving the stack trace of an error or wrapper 66 | // 67 | // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are 68 | // invoked. This information can be retrieved with the following interface. 69 | // 70 | // type stackTracer interface { 71 | // StackTrace() errors.StackTrace 72 | // } 73 | // 74 | // Where errors.StackTrace is defined as 75 | // 76 | // type StackTrace []Frame 77 | // 78 | // The Frame type represents a call site in the stack trace. Frame supports 79 | // the fmt.Formatter interface that can be used for printing information about 80 | // the stack trace of this error. For example: 81 | // 82 | // if err, ok := err.(stackTracer); ok { 83 | // for _, f := range err.StackTrace() { 84 | // fmt.Printf("%+s:%d", f) 85 | // } 86 | // } 87 | // 88 | // stackTracer interface is not exported by this package, but is considered a part 89 | // of stable public API. 90 | // 91 | // See the documentation for Frame.Format for more details. 92 | package errors 93 | 94 | import ( 95 | "fmt" 96 | "io" 97 | ) 98 | 99 | // New returns an error with the supplied message. 100 | // New also records the stack trace at the point it was called. 101 | func New(message string) error { 102 | return &fundamental{ 103 | msg: message, 104 | stack: callers(), 105 | } 106 | } 107 | 108 | // Errorf formats according to a format specifier and returns the string 109 | // as a value that satisfies error. 110 | // Errorf also records the stack trace at the point it was called. 111 | func Errorf(format string, args ...interface{}) error { 112 | return &fundamental{ 113 | msg: fmt.Sprintf(format, args...), 114 | stack: callers(), 115 | } 116 | } 117 | 118 | // fundamental is an error that has a message and a stack, but no caller. 119 | type fundamental struct { 120 | msg string 121 | *stack 122 | } 123 | 124 | func (f *fundamental) Error() string { return f.msg } 125 | 126 | func (f *fundamental) Format(s fmt.State, verb rune) { 127 | switch verb { 128 | case 'v': 129 | if s.Flag('+') { 130 | io.WriteString(s, f.msg) 131 | f.stack.Format(s, verb) 132 | return 133 | } 134 | fallthrough 135 | case 's': 136 | io.WriteString(s, f.msg) 137 | case 'q': 138 | fmt.Fprintf(s, "%q", f.msg) 139 | } 140 | } 141 | 142 | // WithStack annotates err with a stack trace at the point WithStack was called. 143 | // If err is nil, WithStack returns nil. 144 | func WithStack(err error) error { 145 | if err == nil { 146 | return nil 147 | } 148 | return &withStack{ 149 | err, 150 | callers(), 151 | } 152 | } 153 | 154 | type withStack struct { 155 | error 156 | *stack 157 | } 158 | 159 | func (w *withStack) Cause() error { return w.error } 160 | 161 | func (w *withStack) Format(s fmt.State, verb rune) { 162 | switch verb { 163 | case 'v': 164 | if s.Flag('+') { 165 | fmt.Fprintf(s, "%+v", w.Cause()) 166 | w.stack.Format(s, verb) 167 | return 168 | } 169 | fallthrough 170 | case 's': 171 | io.WriteString(s, w.Error()) 172 | case 'q': 173 | fmt.Fprintf(s, "%q", w.Error()) 174 | } 175 | } 176 | 177 | // Wrap returns an error annotating err with a stack trace 178 | // at the point Wrap is called, and the supplied message. 179 | // If err is nil, Wrap returns nil. 180 | func Wrap(err error, message string) error { 181 | if err == nil { 182 | return nil 183 | } 184 | err = &withMessage{ 185 | cause: err, 186 | msg: message, 187 | } 188 | return &withStack{ 189 | err, 190 | callers(), 191 | } 192 | } 193 | 194 | // Wrapf returns an error annotating err with a stack trace 195 | // at the point Wrapf is call, and the format specifier. 196 | // If err is nil, Wrapf returns nil. 197 | func Wrapf(err error, format string, args ...interface{}) error { 198 | if err == nil { 199 | return nil 200 | } 201 | err = &withMessage{ 202 | cause: err, 203 | msg: fmt.Sprintf(format, args...), 204 | } 205 | return &withStack{ 206 | err, 207 | callers(), 208 | } 209 | } 210 | 211 | // WithMessage annotates err with a new message. 212 | // If err is nil, WithMessage returns nil. 213 | func WithMessage(err error, message string) error { 214 | if err == nil { 215 | return nil 216 | } 217 | return &withMessage{ 218 | cause: err, 219 | msg: message, 220 | } 221 | } 222 | 223 | type withMessage struct { 224 | cause error 225 | msg string 226 | } 227 | 228 | func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } 229 | func (w *withMessage) Cause() error { return w.cause } 230 | 231 | func (w *withMessage) Format(s fmt.State, verb rune) { 232 | switch verb { 233 | case 'v': 234 | if s.Flag('+') { 235 | fmt.Fprintf(s, "%+v\n", w.Cause()) 236 | io.WriteString(s, w.msg) 237 | return 238 | } 239 | fallthrough 240 | case 's', 'q': 241 | io.WriteString(s, w.Error()) 242 | } 243 | } 244 | 245 | // Cause returns the underlying cause of the error, if possible. 246 | // An error value has a cause if it implements the following 247 | // interface: 248 | // 249 | // type causer interface { 250 | // Cause() error 251 | // } 252 | // 253 | // If the error does not implement Cause, the original error will 254 | // be returned. If the error is nil, nil will be returned without further 255 | // investigation. 256 | func Cause(err error) error { 257 | type causer interface { 258 | Cause() error 259 | } 260 | 261 | for err != nil { 262 | cause, ok := err.(causer) 263 | if !ok { 264 | break 265 | } 266 | err = cause.Cause() 267 | } 268 | return err 269 | } 270 | -------------------------------------------------------------------------------- /internal/grib2.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | const NCEP = 7 4 | const JMA1 = 34 5 | const JMA2 = 35 6 | 7 | // #define INT1(a) ((a & 0x80) ? - (int) (a & 127) : (int) (a & 127)) 8 | func INT1(a unsigned_char) int { 9 | if (a & 0x80) != 0 { 10 | return -int(a & 127) 11 | } 12 | return int(a & 127) 13 | } 14 | 15 | // #define UINT2(a,b) ((int) ((a << 8) + (b))) 16 | func UINT2(a, b unsigned_char) int { 17 | return (int(a) << 8) + int(b) 18 | } 19 | 20 | // #define GB2_Center(sec) UINT2(sec[1][5], sec[1][6]) 21 | func GB2_Center(sec [][]unsigned_char) int { 22 | return UINT2(sec[1][5], sec[1][6]) 23 | } 24 | 25 | // #define GB2_Sec3_npts(sec) uint4(sec[3]+6) 26 | func GB2_Sec3_npts(sec [][]unsigned_char) unsigned_int { 27 | return uint4(sec[3][6:]) 28 | } 29 | 30 | // #define GDS_Scan_y(scan) ((scan & 64) == 64) 31 | func GDS_Scan_y(scan int) bool { 32 | return (scan & 64) == 64 33 | } 34 | 35 | // #define GDS_Scan_staggered_storage(scan) (((scan) & (1)) != 0) 36 | func GDS_Scan_staggered_storage(scan int) bool { 37 | return ((scan) & (1)) != 0 38 | } 39 | 40 | // #define GDS_LatLon_basic_ang(gds) int4(gds+38) 41 | func GDS_LatLon_basic_ang(gds []unsigned_char) int { 42 | return int4(gds[38:]) 43 | } 44 | 45 | // #define GDS_LatLon_sub_ang(gds) int4(gds+42) 46 | func GDS_LatLon_sub_ang(gds []unsigned_char) int { 47 | return int4(gds[42:]) 48 | } 49 | 50 | // #define GDS_LatLon_lat1(gds) int4(gds+46) 51 | func GDS_LatLon_lat1(gds []unsigned_char) int { 52 | return int4(gds[46:]) 53 | } 54 | 55 | // #define GDS_LatLon_lon1(gds) uint4(gds+50) 56 | func GDS_LatLon_lon1(gds []unsigned_char) unsigned_int { 57 | return uint4(gds[50:]) 58 | } 59 | 60 | // #define GDS_LatLon_lat2(gds) int4(gds+55) 61 | func GDS_LatLon_lat2(gds []unsigned_char) int { 62 | return int4(gds[55:]) 63 | } 64 | 65 | // #define GDS_LatLon_lon2(gds) uint4(gds+59) 66 | func GDS_LatLon_lon2(gds []unsigned_char) unsigned_int { 67 | return uint4(gds[59:]) 68 | } 69 | 70 | // #define GDS_LatLon_dlon(gds) int4(gds+63) 71 | func GDS_LatLon_dlon(gds []unsigned_char) int { 72 | return int4(gds[63:]) 73 | } 74 | 75 | // #define GDS_LatLon_dlat(gds) int4(gds+67) 76 | func GDS_LatLon_dlat(gds []unsigned_char) int { 77 | return int4(gds[67:]) 78 | } 79 | 80 | // #define GDS_Scan_row_rev(scan) ((scan & 16) == 16) 81 | func GDS_Scan_row_rev(scan int) bool { 82 | return (scan & 16) == 16 83 | } 84 | 85 | // #define GDS_Scan_x(scan) ((scan & 128) == 0) 86 | func GDS_Scan_x(scan int) bool { 87 | return (scan & 128) == 0 88 | } 89 | 90 | // #define GB2_ProdDefTemplateNo(sec) (UINT2(sec[4][7],sec[4][8])) 91 | func GB2_ProdDefTemplateNo(sec [][]unsigned_char) int { 92 | return UINT2(sec[4][7], sec[4][8]) 93 | } 94 | 95 | // #define GB2_Discipline(sec) ((int) (sec[0][6])) 96 | func GB2_Discipline(sec [][]unsigned_char) int { 97 | return int(sec[0][6]) 98 | } 99 | 100 | // #define GB2_MasterTable(sec) ((int) (sec[1][9])) 101 | func GB2_MasterTable(sec [][]unsigned_char) int { 102 | return int(sec[1][9]) 103 | } 104 | 105 | // #define GB2_LocalTable(sec) ((int) (sec[1][10])) 106 | func GB2_LocalTable(sec [][]unsigned_char) int { 107 | return int(sec[1][10]) 108 | } 109 | 110 | // #define GB2_ParmCat(sec) (sec[4][9]) 111 | func GB2_ParmCat(sec [][]unsigned_char) int { 112 | return int(sec[4][9]) 113 | } 114 | 115 | // #define GB2_ParmNum(sec) (sec[4][10]) 116 | func GB2_ParmNum(sec [][]unsigned_char) int { 117 | return int(sec[4][10]) 118 | } 119 | 120 | // #define GB2_Subcenter(sec) UINT2(sec[1][7], sec[1][8]) 121 | func GB2_Subcenter(sec [][]unsigned_char) int { 122 | return UINT2(sec[1][7], sec[1][8]) 123 | } 124 | 125 | // #define GDS_RotLatLon_sp_lat(gds) (int4(gds+72)) 126 | func GDS_RotLatLon_sp_lat(gds []unsigned_char) int { 127 | return int4(gds[72:]) 128 | } 129 | 130 | // #define GDS_RotLatLon_sp_lon(gds) (uint4(gds+76)) 131 | func GDS_RotLatLon_sp_lon(gds []unsigned_char) unsigned_int { 132 | return uint4(gds[76:]) 133 | } 134 | 135 | // #define GDS_RotLatLon_rotation(gds) (int4(gds+80)) 136 | func GDS_RotLatLon_rotation(gds []unsigned_char) unsigned_int { 137 | return uint4(gds[80:]) 138 | } 139 | 140 | // #define GDS_Mercator_dy(gds) ((uint4(gds+68))*0.001) 141 | func GDS_Mercator_dy(gds []unsigned_char) double { 142 | return double(uint4(gds[68:])) * 0.001 143 | } 144 | 145 | // #define GDS_Mercator_dx(gds) ((uint4(gds+64))*0.001) 146 | func GDS_Mercator_dx(gds []unsigned_char) double { 147 | return double(uint4(gds[64:])) * 0.001 148 | } 149 | 150 | // #define GDS_Mercator_lat1(gds) (int4(gds+38)*0.000001) 151 | func GDS_Mercator_lat1(gds []unsigned_char) double { 152 | return double(int4(gds[38:])) * 0.000001 153 | } 154 | 155 | // #define GDS_Mercator_lat2(gds) (int4(gds+51)*0.000001) 156 | func GDS_Mercator_lat2(gds []unsigned_char) double { 157 | return double(int4(gds[51:])) * 0.000001 158 | } 159 | 160 | // #define GDS_Mercator_lon1(gds) (uint4(gds+42)*0.000001) 161 | func GDS_Mercator_lon1(gds []unsigned_char) double { 162 | return double(uint4(gds[42:])) * 0.000001 163 | } 164 | 165 | // #define GDS_Mercator_lon2(gds) (uint4(gds+55)*0.000001) 166 | func GDS_Mercator_lon2(gds []unsigned_char) double { 167 | return double(uint4(gds[55:])) * 0.000001 168 | } 169 | 170 | // #define GDS_Mercator_ori_angle(gds) (uint4(gds+60)*0.000001) 171 | func GDS_Mercator_ori_angle(gds []unsigned_char) double { 172 | return double(uint4(gds[60:])) * 0.000001 173 | } 174 | 175 | // #define GDS_Mercator_latD(gds) (int4(gds+47)*0.000001) 176 | func GDS_Mercator_latD(gds []unsigned_char) double { 177 | return double(int4(gds[47:])) * 0.000001 178 | } 179 | 180 | // #define GDS_Polar_lat1(gds) (int4(gds+38)*0.000001) 181 | func GDS_Polar_lat1(gds []unsigned_char) double { 182 | return double(int4(gds[38:])) * 0.000001 183 | } 184 | 185 | // #define GDS_Polar_lon1(gds) (uint4(gds+42)*0.000001) 186 | func GDS_Polar_lon1(gds []unsigned_char) double { 187 | return double(uint4(gds[42:])) * 0.000001 188 | } 189 | 190 | // #define GDS_Polar_lov(gds) (uint4(gds+51)*0.000001) 191 | func GDS_Polar_lov(gds []unsigned_char) double { 192 | return double(uint4(gds[51:])) * 0.000001 193 | } 194 | 195 | // #define GDS_Polar_lad(gds) (int4(gds+47)*0.000001) 196 | func GDS_Polar_lad(gds []unsigned_char) double { 197 | return double(int4(gds[47:])) * 0.000001 198 | } 199 | 200 | // #define GDS_Polar_dx(gds) (uint4(gds+55)*0.001) 201 | func GDS_Polar_dx(gds []unsigned_char) double { 202 | return double(uint4(gds[55:])) * 0.001 203 | } 204 | 205 | // #define GDS_Polar_dy(gds) (uint4(gds+59)*0.001) 206 | func GDS_Polar_dy(gds []unsigned_char) double { 207 | return double(uint4(gds[59:])) * 0.001 208 | } 209 | 210 | // #define GDS_Polar_sps(gds) ((gds[63] & 128) == 128) 211 | func GDS_Polar_sps(gds []unsigned_char) bool { 212 | return (gds[63] & 128) == 128 213 | } 214 | 215 | // #define GDS_Lambert_dy(gds) (int4(gds+59) * 0.001) 216 | func GDS_Lambert_dy(gds []unsigned_char) double { 217 | return double(int4(gds[59:])) * 0.001 218 | } 219 | 220 | // #define GDS_Lambert_dx(gds) (int4(gds+55) * 0.001) 221 | func GDS_Lambert_dx(gds []unsigned_char) double { 222 | return double(int4(gds[55:])) * 0.001 223 | } 224 | 225 | // #define GDS_Lambert_La1(gds) (int4(gds+38) * 0.000001) 226 | func GDS_Lambert_La1(gds []unsigned_char) double { 227 | return double(int4(gds[38:])) * 0.000001 228 | } 229 | 230 | // #define GDS_Lambert_Lo1(gds) (int4(gds+42) * 0.000001) 231 | func GDS_Lambert_Lo1(gds []unsigned_char) double { 232 | return double(int4(gds[42:])) * 0.000001 233 | } 234 | 235 | // #define GDS_Lambert_Lov(gds) (int4(gds+51) * 0.000001) 236 | func GDS_Lambert_Lov(gds []unsigned_char) double { 237 | return double(int4(gds[51:])) * 0.000001 238 | } 239 | 240 | // #define GDS_Lambert_Latin1(gds) (int4(gds+65) * 0.000001) 241 | func GDS_Lambert_Latin1(gds []unsigned_char) double { 242 | return double(int4(gds[65:])) * 0.000001 243 | } 244 | 245 | // #define GDS_Lambert_Latin2(gds) (int4(gds+69) * 0.000001) 246 | func GDS_Lambert_Latin2(gds []unsigned_char) double { 247 | return double(int4(gds[69:])) * 0.000001 248 | } 249 | 250 | // #define GDS_Lambert_LatD(gds) (int4(gds+47) * 0.000001) 251 | func GDS_Lambert_LatD(gds []unsigned_char) double { 252 | return double(int4(gds[47:])) * 0.000001 253 | } 254 | -------------------------------------------------------------------------------- /internal/Sec3.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* 4 | * figures out nx and ny 5 | * res = resolution and component flags table 3.3 6 | * scan = scan mode table 3.4 7 | * 8 | * Use this code rather than .h files for nx, ny, res and scan 9 | */ 10 | /* 11 | int get_nxny(unsigned char **sec, int *nx, int *ny, unsigned int *npnts, int *res, int *scan) { 12 | unsigned int nxx, nyy; 13 | int err; 14 | 15 | err = get_nxny_(sec, &nxx, &nyy, npnts, res, scan); 16 | *nx = nxx == 0 ? -1 : nxx; 17 | *ny = nyy == 0 ? -1 : nyy; 18 | return err; 19 | } 20 | */ 21 | func get_nxny(sec [][]unsigned_char, nx *int, ny *int, npnts *unsigned_int, res *int, scan *int, n_variable_dim *int, variable_dim *[]int, raw_variable_dim *[]int) (err error) { 22 | var nxx, nyy unsigned_int 23 | 24 | err = get_nxny_(sec, &nxx, &nyy, npnts, res, scan, n_variable_dim, variable_dim, raw_variable_dim) 25 | //*nx = nxx == 0 ? -1 : nxx; 26 | if nxx == 0 { 27 | *nx = -1 28 | } else { 29 | *nx = int(nxx) 30 | } 31 | //*ny = nyy == 0 ? -1 : nyy; 32 | if nyy == 0 { 33 | *ny = -1 34 | } else { 35 | *ny = int(nyy) 36 | } 37 | return err 38 | } 39 | 40 | /* 41 | int get_nxny_(unsigned char **sec, unsigned int *nx, unsigned int *ny, unsigned int *npnts, int *res, int *scan) { 42 | int grid_template, n_var_dim, i, j, n_octets, center; 43 | unsigned int npoints, n; 44 | unsigned char *gds, *p; 45 | 46 | center = GB2_Center(sec); 47 | grid_template = code_table_3_1(sec); 48 | *res = flag_table_3_3(sec); 49 | *scan = flag_table_3_4(sec); 50 | gds = sec[3]; 51 | 52 | switch (grid_template) { 53 | case 0: 54 | case 1: 55 | case 2: 56 | case 3: 57 | case 4: 58 | case 5: 59 | case 10: 60 | case 12: 61 | case 20: 62 | case 30: 63 | case 31: 64 | case 40: 65 | case 41: 66 | case 42: 67 | case 43: 68 | case 44: 69 | case 90: 70 | case 110: 71 | case 140: 72 | case 204: 73 | *nx = uint4_missing(gds+30); *ny = uint4_missing(gds+34); break; 74 | case 51: 75 | case 52: 76 | case 53: 77 | case 130: 78 | case 50: *nx = GB2_Sec3_npts(sec); *ny = 1; break; // should calculate for from parameters 79 | 80 | case 120: *nx = uint4_missing(gds+14); // nx = bin along radials, ny = num radials 81 | *ny = uint4_missing(gds+18); 82 | break; 83 | case 32768: 84 | case 32769: 85 | if (center == NCEP) { 86 | *nx = uint4_missing(gds+30); 87 | *ny = uint4_missing(gds+34); 88 | break; 89 | } 90 | *nx = *ny = 0; break; 91 | case 40110: 92 | if ((center == JMA1) || (center == JMA2)) { 93 | *nx = uint4_missing(gds+30); 94 | *ny = uint4_missing(gds+34); 95 | break; 96 | } 97 | *nx = *ny = 0; break; 98 | case 50120: 99 | if ((center == JMA1) || (center == JMA2)) { 100 | *nx = uint4_missing(gds+14); // Nb number of point from origin 101 | *ny = uint4_missing(gds+18); // Nr number of angles 102 | break; 103 | } 104 | *nx = *ny = 0; break; 105 | default: 106 | *nx = *ny = 0; break; 107 | } 108 | 109 | n_var_dim = 0; 110 | if (*nx == 0) n_var_dim = *ny; 111 | if (*ny == 0) n_var_dim = *nx; 112 | if (*nx == 0 && *ny == 0) n_var_dim = 0; 113 | 114 | p = NULL; 115 | if (n_var_dim) { 116 | switch (grid_template) { 117 | case 0: p = gds + 72; break; 118 | case 1: p = gds + 84; break; 119 | case 2: p = gds + 84; break; 120 | case 3: p = gds + 96; break; 121 | case 10: p = gds + 72; break; 122 | case 40: p = gds + 72; break; 123 | case 41: p = gds + 84; break; 124 | case 42: p = gds + 84; break; 125 | case 43: p = gds + 96; break; 126 | case 32768: if (GB2_Center(sec) == NCEP) p = gds + 72; 127 | else p = NULL; 128 | break; 129 | case 32769: if (GB2_Center(sec) == NCEP) p = gds + 80; 130 | else p = NULL; 131 | break; 132 | default: p = NULL; break; 133 | } 134 | } 135 | 136 | /* calculate number of grid points, check with GDS / 137 | npoints = 0; 138 | if (n_var_dim) { 139 | 140 | if (n_variable_dim != n_var_dim) { 141 | if (variable_dim) free(variable_dim); 142 | if (raw_variable_dim) free(raw_variable_dim); 143 | variable_dim = (int *) malloc(n_var_dim * sizeof(int)); 144 | raw_variable_dim = (int *) malloc(n_var_dim * sizeof(int)); 145 | 146 | if (variable_dim == NULL || raw_variable_dim == NULL) 147 | fatal_error("ran out of memory",""); 148 | n_variable_dim = n_var_dim; 149 | } 150 | n_octets = (int) gds[10]; /* number of octets per integer / 151 | for (i = 0; i < n_var_dim; i++) { 152 | for (n = j = 0; j < n_octets; j++) { 153 | n = (n << 8) + (int) *p++; 154 | } 155 | raw_variable_dim[i] = variable_dim[i] = (int) n; 156 | npoints += n; 157 | } 158 | 159 | /* convert variable_dim to SN order if needed / 160 | if (*nx == 0 && GDS_Scan_y(*scan) == 0 && output_order == wesn) { 161 | for (i = 0; i < *ny; i++) { 162 | variable_dim[i] = raw_variable_dim[*ny-1-i]; 163 | } 164 | } 165 | /* convert variable_dim to NS order if needed / 166 | else if (*nx == 0 && GDS_Scan_y(*scan) != 0 && output_order == wens) { 167 | for (i = 0; i < *ny; i++) { 168 | variable_dim[i] = raw_variable_dim[*ny-1-i]; 169 | } 170 | } 171 | } 172 | else if (*nx > 0 && *ny > 0) npoints = (unsigned) *nx * *ny; 173 | *npnts = GB2_Sec3_npts(sec); 174 | 175 | if ((*nx != 0 || *ny != 0) && GB2_Sec3_npts(sec) != npoints && GDS_Scan_staggered_storage(*scan) == 0) { 176 | fprintf(stderr,"two values for number of points %u (GDS) %u (calculated)\n", 177 | GB2_Sec3_npts(sec), npoints); 178 | } 179 | 180 | /* 181 | for (i = 0; i < n_var_dim; i++) { 182 | printf("%d ", variable_dim[i]); 183 | } 184 | / 185 | 186 | return 0; 187 | } 188 | */ 189 | func get_nxny_(sec [][]unsigned_char, nx *unsigned_int, ny *unsigned_int, npnts *unsigned_int, res *int, scan *int, n_variable_dim *int, variable_dim *[]int, raw_variable_dim *[]int) error { 190 | var grid_template, n_var_dim, i, j, n_octets, center int 191 | var npoints, n unsigned_int 192 | var gds, p []unsigned_char 193 | 194 | center = GB2_Center(sec) 195 | grid_template = code_table_3_1(sec) 196 | *res = flag_table_3_3(sec) 197 | *scan = flag_table_3_4(sec) 198 | gds = sec[3] 199 | 200 | switch grid_template { 201 | case 0, 1, 2, 3, 4, 5, 10, 12, 20, 30, 31, 40, 41, 42, 43, 44, 90, 110, 140, 204: 202 | *nx = uint4_missing(gds[30:]) 203 | *ny = uint4_missing(gds[34:]) 204 | case 51, 52, 53, 130, 50: 205 | *nx = GB2_Sec3_npts(sec) 206 | *ny = 1 207 | // should calculate for from parameters 208 | 209 | case 120: 210 | *nx = uint4_missing(gds[14:]) // nx = bin along radials, ny = num radials 211 | *ny = uint4_missing(gds[18:]) 212 | case 32768, 32769: 213 | if center == NCEP { 214 | *nx = uint4_missing(gds[30:]) 215 | *ny = uint4_missing(gds[34:]) 216 | } else { 217 | *nx = 0 218 | *ny = 0 219 | } 220 | case 40110: 221 | if (center == JMA1) || (center == JMA2) { 222 | *nx = uint4_missing(gds[30:]) 223 | *ny = uint4_missing(gds[34:]) 224 | } else { 225 | *nx = 0 226 | *ny = 0 227 | } 228 | case 50120: 229 | if (center == JMA1) || (center == JMA2) { 230 | *nx = uint4_missing(gds[14:]) // Nb number of point from origin 231 | *ny = uint4_missing(gds[18:]) // Nr number of angles 232 | } else { 233 | *nx = 0 234 | *ny = 0 235 | } 236 | default: 237 | *nx = 0 238 | *ny = 0 239 | } 240 | 241 | n_var_dim = 0 242 | if *nx == 0 { 243 | n_var_dim = int(*ny) 244 | } 245 | if *ny == 0 { 246 | n_var_dim = int(*nx) 247 | } 248 | if *nx == 0 && *ny == 0 { 249 | n_var_dim = 0 250 | } 251 | 252 | p = nil 253 | if n_var_dim != 0 { 254 | switch grid_template { 255 | case 0: 256 | p = gds[72:] 257 | case 1: 258 | p = gds[84:] 259 | case 2: 260 | p = gds[84:] 261 | case 3: 262 | p = gds[96:] 263 | case 10: 264 | p = gds[72:] 265 | case 40: 266 | p = gds[72:] 267 | case 41: 268 | p = gds[84:] 269 | case 42: 270 | p = gds[84:] 271 | case 43: 272 | p = gds[96:] 273 | case 32768: 274 | if GB2_Center(sec) == NCEP { 275 | p = gds[72:] 276 | } else { 277 | p = nil 278 | } 279 | case 32769: 280 | if GB2_Center(sec) == NCEP { 281 | p = gds[80:] 282 | } else { 283 | p = nil 284 | } 285 | default: 286 | p = nil 287 | } 288 | } 289 | 290 | /* calculate number of grid points, check with GDS */ 291 | npoints = 0 292 | if n_var_dim != 0 { 293 | 294 | if *n_variable_dim != n_var_dim { 295 | //if (variable_dim) free(variable_dim); 296 | //if (raw_variable_dim) free(raw_variable_dim); 297 | //variable_dim = (int *) malloc(n_var_dim * sizeof(int)); 298 | *variable_dim = make([]int, n_var_dim, n_var_dim) 299 | //raw_variable_dim = (int *) malloc(n_var_dim * sizeof(int)); 300 | *raw_variable_dim = make([]int, n_var_dim, n_var_dim) 301 | 302 | *n_variable_dim = n_var_dim 303 | } 304 | n_octets = int(gds[10]) /* number of octets per integer */ 305 | for i = 0; i < n_var_dim; i++ { 306 | //for (n = j = 0; j < n_octets; j++) { 307 | n = 0 308 | j = 0 309 | pIndex := 0 310 | for ; j < n_octets; j++ { 311 | // n = (n << 8) + int(*p++); 312 | n = (n << 8) + unsigned_int(p[pIndex]) 313 | pIndex++ 314 | } 315 | // raw_variable_dim[i] = variable_dim[i] = (int) n; 316 | (*raw_variable_dim)[i] = int(n) 317 | (*variable_dim)[i] = int(n) 318 | npoints += n 319 | } 320 | 321 | /* convert variable_dim to SN order if needed */ 322 | if *nx == 0 && GDS_Scan_y(*scan) == false && output_order == wesn { 323 | for i = 0; i < int(*ny); i++ { 324 | (*variable_dim)[i] = (*raw_variable_dim)[int(*ny)-1-i] 325 | } 326 | } else if *nx == 0 && GDS_Scan_y(*scan) != false && output_order == wens { 327 | /* convert variable_dim to NS order if needed */ 328 | for i = 0; i < int(*ny); i++ { 329 | (*variable_dim)[i] = (*raw_variable_dim)[int(*ny)-1-i] 330 | } 331 | } 332 | } else if *nx > 0 && *ny > 0 { 333 | npoints = unsigned_int(*nx * *ny) 334 | } 335 | *npnts = unsigned_int(GB2_Sec3_npts(sec)) 336 | 337 | if (*nx != 0 || *ny != 0) && GB2_Sec3_npts(sec) != npoints && GDS_Scan_staggered_storage(*scan) == false { 338 | // fprintf(stderr, "two values for number of points %u (GDS) %u (calculated)\n", 339 | // GB2_Sec3_npts(sec), npoints) 340 | return fprintf("two values for number of points %d (GDS) %d (calculated)", GB2_Sec3_npts(sec), npoints) 341 | } 342 | 343 | /* 344 | for (i = 0; i < n_var_dim; i++) { 345 | printf("%d ", variable_dim[i]); 346 | } 347 | */ 348 | 349 | return nil 350 | } 351 | -------------------------------------------------------------------------------- /internal/Level.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | /* code table 4.5 */ 4 | 5 | var level_table = []string{ 6 | /* 0 */ "reserved", 7 | /* 1 */ "surface", 8 | /* 2 */ "cloud base", 9 | /* 3 */ "cloud top", 10 | /* 4 */ "0C isotherm", 11 | /* 5 */ "level of adiabatic condensation from sfc", 12 | /* 6 */ "max wind", 13 | /* 7 */ "tropopause", 14 | /* 8 */ "top of atmosphere", 15 | /* 9 */ "sea bottom", 16 | /* 10 */ "entire atmosphere", 17 | /* 11 */ "cumulonimbus base", 18 | /* 12 */ "cumulonimbus top", 19 | /* 13 */ "lowest level %g%% integrated cloud cover", 20 | /* 14 */ "level of free convection", 21 | /* 15 */ "convection condensation level", 22 | /* 16 */ "level of neutral buoyancy", 23 | /* 17 */ "reserved", 24 | /* 18 */ "reserved", 25 | /* 19 */ "reserved", 26 | /* 20 */ "%g K level", 27 | /* 21 */ "reserved", 28 | /* 22 */ "reserved", 29 | /* 23 */ "reserved", 30 | /* 24 */ "reserved", 31 | /* 25 */ "reserved", 32 | /* 26 */ "reserved", 33 | /* 27 */ "reserved", 34 | /* 28 */ "reserved", 35 | /* 29 */ "reserved", 36 | /* 30 */ "reserved", 37 | /* 31 */ "reserved", 38 | /* 32 */ "reserved", 39 | /* 33 */ "reserved", 40 | /* 34 */ "reserved", 41 | /* 35 */ "reserved", 42 | /* 36 */ "reserved", 43 | /* 37 */ "reserved", 44 | /* 38 */ "reserved", 45 | /* 39 */ "reserved", 46 | /* 40 */ "reserved", 47 | /* 41 */ "reserved", 48 | /* 42 */ "reserved", 49 | /* 43 */ "reserved", 50 | /* 44 */ "reserved", 51 | /* 45 */ "reserved", 52 | /* 46 */ "reserved", 53 | /* 47 */ "reserved", 54 | /* 48 */ "reserved", 55 | /* 49 */ "reserved", 56 | /* 50 */ "reserved", 57 | /* 51 */ "reserved", 58 | /* 52 */ "reserved", 59 | /* 53 */ "reserved", 60 | /* 54 */ "reserved", 61 | /* 55 */ "reserved", 62 | /* 56 */ "reserved", 63 | /* 57 */ "reserved", 64 | /* 58 */ "reserved", 65 | /* 59 */ "reserved", 66 | /* 60 */ "reserved", 67 | /* 61 */ "reserved", 68 | /* 62 */ "reserved", 69 | /* 63 */ "reserved", 70 | /* 64 */ "reserved", 71 | /* 65 */ "reserved", 72 | /* 66 */ "reserved", 73 | /* 67 */ "reserved", 74 | /* 68 */ "reserved", 75 | /* 69 */ "reserved", 76 | /* 70 */ "reserved", 77 | /* 71 */ "reserved", 78 | /* 72 */ "reserved", 79 | /* 73 */ "reserved", 80 | /* 74 */ "reserved", 81 | /* 75 */ "reserved", 82 | /* 76 */ "reserved", 83 | /* 77 */ "reserved", 84 | /* 78 */ "reserved", 85 | /* 79 */ "reserved", 86 | /* 80 */ "reserved", 87 | /* 81 */ "reserved", 88 | /* 82 */ "reserved", 89 | /* 83 */ "reserved", 90 | /* 84 */ "reserved", 91 | /* 85 */ "reserved", 92 | /* 86 */ "reserved", 93 | /* 87 */ "reserved", 94 | /* 88 */ "reserved", 95 | /* 89 */ "reserved", 96 | /* 90 */ "reserved", 97 | /* 91 */ "reserved", 98 | /* 92 */ "reserved", 99 | /* 93 */ "reserved", 100 | /* 94 */ "reserved", 101 | /* 95 */ "reserved", 102 | /* 96 */ "reserved", 103 | /* 97 */ "reserved", 104 | /* 98 */ "reserved", 105 | /* 99 */ "reserved", 106 | /* 100 */ "%g mb", 107 | /* 101 */ "mean sea level", 108 | /* 102 */ "%g m above mean sea level", 109 | /* 103 */ "%g m above ground", 110 | /* 104 */ "%g sigma level", 111 | /* 105 */ "%g hybrid level", 112 | /* 106 */ "%g m underground", 113 | /* 107 */ "%g K isentropic level", 114 | /* 108 */ "%g mb above ground", 115 | /* 109 */ "PV=%g (Km^2/kg/s) surface", 116 | /* 110 */ "reserved", 117 | /* 111 */ "%g Eta level", 118 | /* 112 */ "reserved", 119 | /* 113 */ "logarithmic hybrid level", 120 | /* 114 */ "snow level", 121 | /* 115 */ "reserved", 122 | /* 116 */ "reserved", 123 | /* 117 */ "mixed layer depth", 124 | /* 118 */ "hybrid height level", 125 | /* 119 */ "hybrid pressure level", 126 | /* 120 */ "reserved", 127 | /* 121 */ "reserved", 128 | /* 122 */ "reserved", 129 | /* 123 */ "reserved", 130 | /* 124 */ "reserved", 131 | /* 125 */ "reserved", 132 | /* 126 */ "reserved", 133 | /* 127 */ "reserved", 134 | /* 128 */ "reserved", 135 | /* 129 */ "reserved", 136 | /* 130 */ "reserved", 137 | /* 131 */ "reserved", 138 | /* 132 */ "reserved", 139 | /* 133 */ "reserved", 140 | /* 134 */ "reserved", 141 | /* 135 */ "reserved", 142 | /* 136 */ "reserved", 143 | /* 137 */ "reserved", 144 | /* 138 */ "reserved", 145 | /* 139 */ "reserved", 146 | /* 140 */ "reserved", 147 | /* 141 */ "reserved", 148 | /* 142 */ "reserved", 149 | /* 143 */ "reserved", 150 | /* 144 */ "reserved", 151 | /* 145 */ "reserved", 152 | /* 146 */ "reserved", 153 | /* 147 */ "reserved", 154 | /* 148 */ "reserved", 155 | /* 149 */ "reserved", 156 | /* 150 */ "%g generalized vertical height coordinate", 157 | /* 151 */ "soil level %g", 158 | /* 152 */ "reserved", 159 | /* 153 */ "reserved", 160 | /* 154 */ "reserved", 161 | /* 155 */ "reserved", 162 | /* 156 */ "reserved", 163 | /* 157 */ "reserved", 164 | /* 158 */ "reserved", 165 | /* 159 */ "reserved", 166 | /* 160 */ "%g m below sea level", 167 | /* 161 */ "%g m below water surface", 168 | /* 162 */ "lake or river bottom", 169 | /* 163 */ "bottom of sediment layer", 170 | /* 164 */ "bottom of thermally active sediment layer", 171 | /* 165 */ "bottom of sediment layer penetrated by thermal wave", 172 | /* 166 */ "maxing layer", 173 | /* 167 */ "bottom of root zone", 174 | /* 168 */ "reserved", 175 | /* 169 */ "reserved", 176 | /* 170 */ "reserved", 177 | /* 171 */ "reserved", 178 | /* 172 */ "reserved", 179 | /* 173 */ "reserved", 180 | /* 174 */ "top surface of ice on sea, lake or river", 181 | /* 175 */ "top surface of ice, und snow on sea, lake or river", 182 | /* 176 */ "bottom surface ice on sea, lake or river", 183 | /* 177 */ "deep soil", 184 | /* 178 */ "reserved", 185 | /* 179 */ "top surface of glacier ice and inland ice", 186 | /* 180 */ "deep inland or glacier ice", 187 | /* 181 */ "grid tile land fraction as a model surface", 188 | /* 182 */ "grid tile water fraction as a model surface", 189 | /* 183 */ "grid tile ice fraction on sea, lake or river as a model surface", 190 | /* 184 */ "grid tile glacier ice and inland ice fraction as a model surface", 191 | /* 185 */ "reserved", 192 | /* 186 */ "reserved", 193 | /* 187 */ "reserved", 194 | /* 188 */ "reserved", 195 | /* 189 */ "reserved", 196 | /* 190 */ "reserved", 197 | /* 191 */ "reserved", 198 | } 199 | 200 | func f_lev(sec [][]unsigned_char, inv_out *string) error { 201 | 202 | var level_type1, level_type2 int 203 | var val1, val2 float 204 | var undef_val1, undef_val2 int 205 | var center, subcenter int 206 | 207 | center = GB2_Center(sec) 208 | subcenter = GB2_Subcenter(sec) 209 | 210 | err := fixed_surfaces(sec, &level_type1, &val1, &undef_val1, &level_type2, &val2, &undef_val2) 211 | if err != nil { 212 | return fatal_error_wrap(err, "Failed to execute fixed_surfaces") 213 | } 214 | 215 | /* 216 | if mode > 1 { 217 | if undef_val1 == 0 { 218 | sprintf(inv_out, "lvl1=(%d,%lg) ", level_type1, val1) 219 | } else { 220 | sprintf(inv_out, "lvl1=(%d,missing) ", level_type1) 221 | } 222 | inv_out += strlen(inv_out) 223 | 224 | if undef_val2 == 0 { 225 | sprintf(inv_out, "lvl2=(%d,%lg):", level_type2, val2) 226 | } else { 227 | sprintf(inv_out, "lvl2=(%d,missing):", level_type2) 228 | } 229 | inv_out += strlen(inv_out) 230 | } 231 | */ 232 | level2(level_type1, undef_val1, val1, level_type2, undef_val2, val2, center, subcenter, inv_out) 233 | return nil 234 | } 235 | 236 | /* 237 | * level2 is for layers 238 | */ 239 | 240 | func level2(type1 int, undef_val1 int, value1 float, type2 int, undef_val2 int, value2 float, center int, subcenter int, inv_out *string) { 241 | if type1 == 100 && type2 == 100 { 242 | *inv_out += sprintf("%g-%g mb", value1/100, value2/100) 243 | } else if type1 == 102 && type2 == 102 { 244 | *inv_out += sprintf("%g-%g m above mean sea level", value1, value2) 245 | } else if type1 == 103 && type2 == 103 { 246 | *inv_out += sprintf("%g-%g m above ground", value1, value2) 247 | } else if type1 == 104 && type2 == 104 { 248 | *inv_out += sprintf("%g-%g sigma layer", value1, value2) 249 | } else if type1 == 105 && type2 == 105 { 250 | *inv_out += sprintf("%g-%g hybrid layer", value1, value2) 251 | } else if type1 == 106 && type2 == 106 { 252 | /* sprintf(inv_out,"%g-%g m below ground",value1/100,value2/100); removed 1/2007 */ 253 | *inv_out += sprintf("%g-%g m below ground", value1, value2) 254 | } else if type1 == 107 && type2 == 107 { 255 | *inv_out += sprintf("%g-%g K isentropic layer", value1, value2) 256 | } else if type1 == 108 && type2 == 108 { 257 | *inv_out += sprintf("%g-%g mb above ground", value1/100, value2/100) 258 | } else if type1 == 160 && type2 == 160 { 259 | *inv_out += sprintf("%g-%g m below sea level", value1, value2) 260 | } else if type1 == 161 && type2 == 161 { 261 | *inv_out += sprintf("%g-%g m ocean layer", value1, value2) 262 | } else if type1 == 1 && type2 == 8 { 263 | *inv_out += sprintf("atmos col") // compatible with wgrib 264 | } else if type1 == 9 && type2 == 1 { 265 | *inv_out += sprintf("ocean column") 266 | } else if center == NCEP && type1 == 235 && type2 == 235 { 267 | *inv_out += sprintf("%g-%gC ocean isotherm layer", value1/10, value2/10) 268 | } else if center == NCEP && type1 == 236 && type2 == 236 { // obsolete 269 | *inv_out += sprintf("%g-%g m ocean layer", value1*10, value2*10) 270 | } else if type1 == 255 && type2 == 255 { 271 | *inv_out += sprintf("no_level") 272 | } else { 273 | level1(type1, undef_val1, value1, center, subcenter, inv_out) 274 | if type2 != 255 { 275 | *inv_out += " - " 276 | level1(type2, undef_val2, value2, center, subcenter, inv_out) 277 | } 278 | } 279 | } 280 | 281 | /* 282 | * level1 is for a single level (not a layer) 283 | */ 284 | func level1(type_ int, undef_val int, val float, center int, subcenter int, inv_out *string) { 285 | 286 | var string_ string 287 | 288 | /* local table for NCEP */ 289 | if center == NCEP && type_ >= 192 && type_ <= 254 { 290 | if type_ == 235 { 291 | *inv_out += sprintf("%gC ocean isotherm", val/10) 292 | return 293 | } 294 | if type_ == 241 { 295 | *inv_out += sprintf("%g in sequence", val) 296 | } 297 | 298 | switch type_ { 299 | case 200: 300 | string_ = "entire atmosphere (considered as a single layer)" 301 | case 201: 302 | string_ = "entire ocean (considered as a single layer)" 303 | case 204: 304 | string_ = "highest tropospheric freezing level" 305 | case 206: 306 | string_ = "grid scale cloud bottom level" 307 | case 207: 308 | string_ = "grid scale cloud top level" 309 | case 209: 310 | string_ = "boundary layer cloud bottom level" 311 | case 210: 312 | string_ = "boundary layer cloud top level" 313 | case 211: 314 | string_ = "boundary layer cloud layer" 315 | case 212: 316 | string_ = "low cloud bottom level" 317 | case 213: 318 | string_ = "low cloud top level" 319 | case 214: 320 | string_ = "low cloud layer" 321 | case 215: 322 | string_ = "cloud ceiling" 323 | case 220: 324 | string_ = "planetary boundary layer" 325 | case 221: 326 | string_ = "layer between two hybrid levels" 327 | case 222: 328 | string_ = "middle cloud bottom level" 329 | case 223: 330 | string_ = "middle cloud top level" 331 | case 224: 332 | string_ = "middle cloud layer" 333 | case 232: 334 | string_ = "high cloud bottom level" 335 | case 233: 336 | string_ = "high cloud top level" 337 | case 234: 338 | string_ = "high cloud layer" 339 | case 235: 340 | string_ = "ocean isotherm level (1/10 deg C)" 341 | case 236: 342 | string_ = "layer between two depths below ocean surface" 343 | case 237: 344 | string_ = "bottom of ocean mixed layer" 345 | case 238: 346 | string_ = "bottom of ocean isothermal layer" 347 | case 239: 348 | string_ = "layer ocean surface and 26C ocean isothermal level" 349 | case 240: 350 | string_ = "ocean mixed layer" 351 | case 241: 352 | string_ = "ordered sequence of data" 353 | case 242: 354 | string_ = "convective cloud bottom level" 355 | case 243: 356 | string_ = "convective cloud top level" 357 | case 244: 358 | string_ = "convective cloud layer" 359 | case 245: 360 | string_ = "lowest level of the wet bulb zero" 361 | case 246: 362 | string_ = "maximum equivalent potential temperature level" 363 | case 247: 364 | string_ = "equilibrium level" 365 | case 248: 366 | string_ = "shallow convective cloud bottom level" 367 | case 249: 368 | string_ = "shallow convective cloud top level" 369 | case 251: 370 | string_ = "deep convective cloud bottom level" 371 | case 252: 372 | string_ = "deep convective cloud top level" 373 | case 253: 374 | string_ = "lowest bottom level of supercooled liquid water layer" 375 | case 254: 376 | string_ = "highest top level of supercooled liquid water layer" 377 | } 378 | if len(string_) > 0 { 379 | *inv_out += sprintf(string_, val) 380 | return 381 | } 382 | } 383 | 384 | if type_ == 100 || type_ == 108 { 385 | val = val * 0.01 386 | } // Pa -> mb 387 | 388 | // no numeric information 389 | if type_ == 255 { 390 | return 391 | } 392 | 393 | if type_ < 192 { 394 | *inv_out += sprintf(level_table[type_], val) 395 | } else if center == NCEP { 396 | if undef_val == 0 { 397 | *inv_out += sprintf("NCEP level type %d %g", type_, val) 398 | } else { 399 | *inv_out += sprintf("NCEP level type %d", type_) 400 | } 401 | } else { 402 | if undef_val == 0 { 403 | *inv_out += sprintf("local level type %d %g", type_, val) 404 | } else { 405 | *inv_out += sprintf("local level type %d", type_) 406 | } 407 | } 408 | 409 | return 410 | } 411 | -------------------------------------------------------------------------------- /vendor/github.com/pkg/errors/format_test.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "regexp" 8 | "strings" 9 | "testing" 10 | ) 11 | 12 | func TestFormatNew(t *testing.T) { 13 | tests := []struct { 14 | error 15 | format string 16 | want string 17 | }{{ 18 | New("error"), 19 | "%s", 20 | "error", 21 | }, { 22 | New("error"), 23 | "%v", 24 | "error", 25 | }, { 26 | New("error"), 27 | "%+v", 28 | "error\n" + 29 | "github.com/pkg/errors.TestFormatNew\n" + 30 | "\t.+/github.com/pkg/errors/format_test.go:26", 31 | }, { 32 | New("error"), 33 | "%q", 34 | `"error"`, 35 | }} 36 | 37 | for i, tt := range tests { 38 | testFormatRegexp(t, i, tt.error, tt.format, tt.want) 39 | } 40 | } 41 | 42 | func TestFormatErrorf(t *testing.T) { 43 | tests := []struct { 44 | error 45 | format string 46 | want string 47 | }{{ 48 | Errorf("%s", "error"), 49 | "%s", 50 | "error", 51 | }, { 52 | Errorf("%s", "error"), 53 | "%v", 54 | "error", 55 | }, { 56 | Errorf("%s", "error"), 57 | "%+v", 58 | "error\n" + 59 | "github.com/pkg/errors.TestFormatErrorf\n" + 60 | "\t.+/github.com/pkg/errors/format_test.go:56", 61 | }} 62 | 63 | for i, tt := range tests { 64 | testFormatRegexp(t, i, tt.error, tt.format, tt.want) 65 | } 66 | } 67 | 68 | func TestFormatWrap(t *testing.T) { 69 | tests := []struct { 70 | error 71 | format string 72 | want string 73 | }{{ 74 | Wrap(New("error"), "error2"), 75 | "%s", 76 | "error2: error", 77 | }, { 78 | Wrap(New("error"), "error2"), 79 | "%v", 80 | "error2: error", 81 | }, { 82 | Wrap(New("error"), "error2"), 83 | "%+v", 84 | "error\n" + 85 | "github.com/pkg/errors.TestFormatWrap\n" + 86 | "\t.+/github.com/pkg/errors/format_test.go:82", 87 | }, { 88 | Wrap(io.EOF, "error"), 89 | "%s", 90 | "error: EOF", 91 | }, { 92 | Wrap(io.EOF, "error"), 93 | "%v", 94 | "error: EOF", 95 | }, { 96 | Wrap(io.EOF, "error"), 97 | "%+v", 98 | "EOF\n" + 99 | "error\n" + 100 | "github.com/pkg/errors.TestFormatWrap\n" + 101 | "\t.+/github.com/pkg/errors/format_test.go:96", 102 | }, { 103 | Wrap(Wrap(io.EOF, "error1"), "error2"), 104 | "%+v", 105 | "EOF\n" + 106 | "error1\n" + 107 | "github.com/pkg/errors.TestFormatWrap\n" + 108 | "\t.+/github.com/pkg/errors/format_test.go:103\n", 109 | }, { 110 | Wrap(New("error with space"), "context"), 111 | "%q", 112 | `"context: error with space"`, 113 | }} 114 | 115 | for i, tt := range tests { 116 | testFormatRegexp(t, i, tt.error, tt.format, tt.want) 117 | } 118 | } 119 | 120 | func TestFormatWrapf(t *testing.T) { 121 | tests := []struct { 122 | error 123 | format string 124 | want string 125 | }{{ 126 | Wrapf(io.EOF, "error%d", 2), 127 | "%s", 128 | "error2: EOF", 129 | }, { 130 | Wrapf(io.EOF, "error%d", 2), 131 | "%v", 132 | "error2: EOF", 133 | }, { 134 | Wrapf(io.EOF, "error%d", 2), 135 | "%+v", 136 | "EOF\n" + 137 | "error2\n" + 138 | "github.com/pkg/errors.TestFormatWrapf\n" + 139 | "\t.+/github.com/pkg/errors/format_test.go:134", 140 | }, { 141 | Wrapf(New("error"), "error%d", 2), 142 | "%s", 143 | "error2: error", 144 | }, { 145 | Wrapf(New("error"), "error%d", 2), 146 | "%v", 147 | "error2: error", 148 | }, { 149 | Wrapf(New("error"), "error%d", 2), 150 | "%+v", 151 | "error\n" + 152 | "github.com/pkg/errors.TestFormatWrapf\n" + 153 | "\t.+/github.com/pkg/errors/format_test.go:149", 154 | }} 155 | 156 | for i, tt := range tests { 157 | testFormatRegexp(t, i, tt.error, tt.format, tt.want) 158 | } 159 | } 160 | 161 | func TestFormatWithStack(t *testing.T) { 162 | tests := []struct { 163 | error 164 | format string 165 | want []string 166 | }{{ 167 | WithStack(io.EOF), 168 | "%s", 169 | []string{"EOF"}, 170 | }, { 171 | WithStack(io.EOF), 172 | "%v", 173 | []string{"EOF"}, 174 | }, { 175 | WithStack(io.EOF), 176 | "%+v", 177 | []string{"EOF", 178 | "github.com/pkg/errors.TestFormatWithStack\n" + 179 | "\t.+/github.com/pkg/errors/format_test.go:175"}, 180 | }, { 181 | WithStack(New("error")), 182 | "%s", 183 | []string{"error"}, 184 | }, { 185 | WithStack(New("error")), 186 | "%v", 187 | []string{"error"}, 188 | }, { 189 | WithStack(New("error")), 190 | "%+v", 191 | []string{"error", 192 | "github.com/pkg/errors.TestFormatWithStack\n" + 193 | "\t.+/github.com/pkg/errors/format_test.go:189", 194 | "github.com/pkg/errors.TestFormatWithStack\n" + 195 | "\t.+/github.com/pkg/errors/format_test.go:189"}, 196 | }, { 197 | WithStack(WithStack(io.EOF)), 198 | "%+v", 199 | []string{"EOF", 200 | "github.com/pkg/errors.TestFormatWithStack\n" + 201 | "\t.+/github.com/pkg/errors/format_test.go:197", 202 | "github.com/pkg/errors.TestFormatWithStack\n" + 203 | "\t.+/github.com/pkg/errors/format_test.go:197"}, 204 | }, { 205 | WithStack(WithStack(Wrapf(io.EOF, "message"))), 206 | "%+v", 207 | []string{"EOF", 208 | "message", 209 | "github.com/pkg/errors.TestFormatWithStack\n" + 210 | "\t.+/github.com/pkg/errors/format_test.go:205", 211 | "github.com/pkg/errors.TestFormatWithStack\n" + 212 | "\t.+/github.com/pkg/errors/format_test.go:205", 213 | "github.com/pkg/errors.TestFormatWithStack\n" + 214 | "\t.+/github.com/pkg/errors/format_test.go:205"}, 215 | }, { 216 | WithStack(Errorf("error%d", 1)), 217 | "%+v", 218 | []string{"error1", 219 | "github.com/pkg/errors.TestFormatWithStack\n" + 220 | "\t.+/github.com/pkg/errors/format_test.go:216", 221 | "github.com/pkg/errors.TestFormatWithStack\n" + 222 | "\t.+/github.com/pkg/errors/format_test.go:216"}, 223 | }} 224 | 225 | for i, tt := range tests { 226 | testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true) 227 | } 228 | } 229 | 230 | func TestFormatWithMessage(t *testing.T) { 231 | tests := []struct { 232 | error 233 | format string 234 | want []string 235 | }{{ 236 | WithMessage(New("error"), "error2"), 237 | "%s", 238 | []string{"error2: error"}, 239 | }, { 240 | WithMessage(New("error"), "error2"), 241 | "%v", 242 | []string{"error2: error"}, 243 | }, { 244 | WithMessage(New("error"), "error2"), 245 | "%+v", 246 | []string{ 247 | "error", 248 | "github.com/pkg/errors.TestFormatWithMessage\n" + 249 | "\t.+/github.com/pkg/errors/format_test.go:244", 250 | "error2"}, 251 | }, { 252 | WithMessage(io.EOF, "addition1"), 253 | "%s", 254 | []string{"addition1: EOF"}, 255 | }, { 256 | WithMessage(io.EOF, "addition1"), 257 | "%v", 258 | []string{"addition1: EOF"}, 259 | }, { 260 | WithMessage(io.EOF, "addition1"), 261 | "%+v", 262 | []string{"EOF", "addition1"}, 263 | }, { 264 | WithMessage(WithMessage(io.EOF, "addition1"), "addition2"), 265 | "%v", 266 | []string{"addition2: addition1: EOF"}, 267 | }, { 268 | WithMessage(WithMessage(io.EOF, "addition1"), "addition2"), 269 | "%+v", 270 | []string{"EOF", "addition1", "addition2"}, 271 | }, { 272 | Wrap(WithMessage(io.EOF, "error1"), "error2"), 273 | "%+v", 274 | []string{"EOF", "error1", "error2", 275 | "github.com/pkg/errors.TestFormatWithMessage\n" + 276 | "\t.+/github.com/pkg/errors/format_test.go:272"}, 277 | }, { 278 | WithMessage(Errorf("error%d", 1), "error2"), 279 | "%+v", 280 | []string{"error1", 281 | "github.com/pkg/errors.TestFormatWithMessage\n" + 282 | "\t.+/github.com/pkg/errors/format_test.go:278", 283 | "error2"}, 284 | }, { 285 | WithMessage(WithStack(io.EOF), "error"), 286 | "%+v", 287 | []string{ 288 | "EOF", 289 | "github.com/pkg/errors.TestFormatWithMessage\n" + 290 | "\t.+/github.com/pkg/errors/format_test.go:285", 291 | "error"}, 292 | }, { 293 | WithMessage(Wrap(WithStack(io.EOF), "inside-error"), "outside-error"), 294 | "%+v", 295 | []string{ 296 | "EOF", 297 | "github.com/pkg/errors.TestFormatWithMessage\n" + 298 | "\t.+/github.com/pkg/errors/format_test.go:293", 299 | "inside-error", 300 | "github.com/pkg/errors.TestFormatWithMessage\n" + 301 | "\t.+/github.com/pkg/errors/format_test.go:293", 302 | "outside-error"}, 303 | }} 304 | 305 | for i, tt := range tests { 306 | testFormatCompleteCompare(t, i, tt.error, tt.format, tt.want, true) 307 | } 308 | } 309 | 310 | func TestFormatGeneric(t *testing.T) { 311 | starts := []struct { 312 | err error 313 | want []string 314 | }{ 315 | {New("new-error"), []string{ 316 | "new-error", 317 | "github.com/pkg/errors.TestFormatGeneric\n" + 318 | "\t.+/github.com/pkg/errors/format_test.go:315"}, 319 | }, {Errorf("errorf-error"), []string{ 320 | "errorf-error", 321 | "github.com/pkg/errors.TestFormatGeneric\n" + 322 | "\t.+/github.com/pkg/errors/format_test.go:319"}, 323 | }, {errors.New("errors-new-error"), []string{ 324 | "errors-new-error"}, 325 | }, 326 | } 327 | 328 | wrappers := []wrapper{ 329 | { 330 | func(err error) error { return WithMessage(err, "with-message") }, 331 | []string{"with-message"}, 332 | }, { 333 | func(err error) error { return WithStack(err) }, 334 | []string{ 335 | "github.com/pkg/errors.(func·002|TestFormatGeneric.func2)\n\t" + 336 | ".+/github.com/pkg/errors/format_test.go:333", 337 | }, 338 | }, { 339 | func(err error) error { return Wrap(err, "wrap-error") }, 340 | []string{ 341 | "wrap-error", 342 | "github.com/pkg/errors.(func·003|TestFormatGeneric.func3)\n\t" + 343 | ".+/github.com/pkg/errors/format_test.go:339", 344 | }, 345 | }, { 346 | func(err error) error { return Wrapf(err, "wrapf-error%d", 1) }, 347 | []string{ 348 | "wrapf-error1", 349 | "github.com/pkg/errors.(func·004|TestFormatGeneric.func4)\n\t" + 350 | ".+/github.com/pkg/errors/format_test.go:346", 351 | }, 352 | }, 353 | } 354 | 355 | for s := range starts { 356 | err := starts[s].err 357 | want := starts[s].want 358 | testFormatCompleteCompare(t, s, err, "%+v", want, false) 359 | testGenericRecursive(t, err, want, wrappers, 3) 360 | } 361 | } 362 | 363 | func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) { 364 | got := fmt.Sprintf(format, arg) 365 | gotLines := strings.SplitN(got, "\n", -1) 366 | wantLines := strings.SplitN(want, "\n", -1) 367 | 368 | if len(wantLines) > len(gotLines) { 369 | t.Errorf("test %d: wantLines(%d) > gotLines(%d):\n got: %q\nwant: %q", n+1, len(wantLines), len(gotLines), got, want) 370 | return 371 | } 372 | 373 | for i, w := range wantLines { 374 | match, err := regexp.MatchString(w, gotLines[i]) 375 | if err != nil { 376 | t.Fatal(err) 377 | } 378 | if !match { 379 | t.Errorf("test %d: line %d: fmt.Sprintf(%q, err):\n got: %q\nwant: %q", n+1, i+1, format, got, want) 380 | } 381 | } 382 | } 383 | 384 | var stackLineR = regexp.MustCompile(`\.`) 385 | 386 | // parseBlocks parses input into a slice, where: 387 | // - incase entry contains a newline, its a stacktrace 388 | // - incase entry contains no newline, its a solo line. 389 | // 390 | // Detecting stack boundaries only works incase the WithStack-calls are 391 | // to be found on the same line, thats why it is optionally here. 392 | // 393 | // Example use: 394 | // 395 | // for _, e := range blocks { 396 | // if strings.ContainsAny(e, "\n") { 397 | // // Match as stack 398 | // } else { 399 | // // Match as line 400 | // } 401 | // } 402 | // 403 | func parseBlocks(input string, detectStackboundaries bool) ([]string, error) { 404 | var blocks []string 405 | 406 | stack := "" 407 | wasStack := false 408 | lines := map[string]bool{} // already found lines 409 | 410 | for _, l := range strings.Split(input, "\n") { 411 | isStackLine := stackLineR.MatchString(l) 412 | 413 | switch { 414 | case !isStackLine && wasStack: 415 | blocks = append(blocks, stack, l) 416 | stack = "" 417 | lines = map[string]bool{} 418 | case isStackLine: 419 | if wasStack { 420 | // Detecting two stacks after another, possible cause lines match in 421 | // our tests due to WithStack(WithStack(io.EOF)) on same line. 422 | if detectStackboundaries { 423 | if lines[l] { 424 | if len(stack) == 0 { 425 | return nil, errors.New("len of block must not be zero here") 426 | } 427 | 428 | blocks = append(blocks, stack) 429 | stack = l 430 | lines = map[string]bool{l: true} 431 | continue 432 | } 433 | } 434 | 435 | stack = stack + "\n" + l 436 | } else { 437 | stack = l 438 | } 439 | lines[l] = true 440 | case !isStackLine && !wasStack: 441 | blocks = append(blocks, l) 442 | default: 443 | return nil, errors.New("must not happen") 444 | } 445 | 446 | wasStack = isStackLine 447 | } 448 | 449 | // Use up stack 450 | if stack != "" { 451 | blocks = append(blocks, stack) 452 | } 453 | return blocks, nil 454 | } 455 | 456 | func testFormatCompleteCompare(t *testing.T, n int, arg interface{}, format string, want []string, detectStackBoundaries bool) { 457 | gotStr := fmt.Sprintf(format, arg) 458 | 459 | got, err := parseBlocks(gotStr, detectStackBoundaries) 460 | if err != nil { 461 | t.Fatal(err) 462 | } 463 | 464 | if len(got) != len(want) { 465 | t.Fatalf("test %d: fmt.Sprintf(%s, err) -> wrong number of blocks: got(%d) want(%d)\n got: %s\nwant: %s\ngotStr: %q", 466 | n+1, format, len(got), len(want), prettyBlocks(got), prettyBlocks(want), gotStr) 467 | } 468 | 469 | for i := range got { 470 | if strings.ContainsAny(want[i], "\n") { 471 | // Match as stack 472 | match, err := regexp.MatchString(want[i], got[i]) 473 | if err != nil { 474 | t.Fatal(err) 475 | } 476 | if !match { 477 | t.Fatalf("test %d: block %d: fmt.Sprintf(%q, err):\ngot:\n%q\nwant:\n%q\nall-got:\n%s\nall-want:\n%s\n", 478 | n+1, i+1, format, got[i], want[i], prettyBlocks(got), prettyBlocks(want)) 479 | } 480 | } else { 481 | // Match as message 482 | if got[i] != want[i] { 483 | t.Fatalf("test %d: fmt.Sprintf(%s, err) at block %d got != want:\n got: %q\nwant: %q", n+1, format, i+1, got[i], want[i]) 484 | } 485 | } 486 | } 487 | } 488 | 489 | type wrapper struct { 490 | wrap func(err error) error 491 | want []string 492 | } 493 | 494 | func prettyBlocks(blocks []string, prefix ...string) string { 495 | var out []string 496 | 497 | for _, b := range blocks { 498 | out = append(out, fmt.Sprintf("%v", b)) 499 | } 500 | 501 | return " " + strings.Join(out, "\n ") 502 | } 503 | 504 | func testGenericRecursive(t *testing.T, beforeErr error, beforeWant []string, list []wrapper, maxDepth int) { 505 | if len(beforeWant) == 0 { 506 | panic("beforeWant must not be empty") 507 | } 508 | for _, w := range list { 509 | if len(w.want) == 0 { 510 | panic("want must not be empty") 511 | } 512 | 513 | err := w.wrap(beforeErr) 514 | 515 | // Copy required cause append(beforeWant, ..) modified beforeWant subtly. 516 | beforeCopy := make([]string, len(beforeWant)) 517 | copy(beforeCopy, beforeWant) 518 | 519 | beforeWant := beforeCopy 520 | last := len(beforeWant) - 1 521 | var want []string 522 | 523 | // Merge two stacks behind each other. 524 | if strings.ContainsAny(beforeWant[last], "\n") && strings.ContainsAny(w.want[0], "\n") { 525 | want = append(beforeWant[:last], append([]string{beforeWant[last] + "((?s).*)" + w.want[0]}, w.want[1:]...)...) 526 | } else { 527 | want = append(beforeWant, w.want...) 528 | } 529 | 530 | testFormatCompleteCompare(t, maxDepth, err, "%+v", want, false) 531 | if maxDepth > 0 { 532 | testGenericRecursive(t, err, want, list, maxDepth-1) 533 | } 534 | } 535 | } 536 | -------------------------------------------------------------------------------- /internal/geo.c.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | const M_PI = 3.14159265358979323846 4 | 5 | const M_PI_4 = 0.78539816339744830962 /* pi/4 */ 6 | 7 | const M_PI_2 = 1.57079632679489661923 /* pi/2 */ 8 | 9 | func todegrees(x double) double { 10 | return x * (180.0 / M_PI) 11 | } 12 | 13 | func regular2ll(sec [][]unsigned_char, lat *[]double, lon *[]double) error { 14 | 15 | var basic_ang, sub_ang int 16 | var units, dlat, dlon, lat1, lat2, lon1, lon2 double 17 | var e, w, n, s, dx, dy double 18 | 19 | var i, j unsigned_int 20 | var llat, llon []double 21 | var gds []unsigned_char 22 | var nnx, nny unsigned_int 23 | var nres, nscan int 24 | var nnpnts unsigned_int 25 | 26 | var n_variable_dim int 27 | var variable_dim, raw_variable_dim []int 28 | 29 | get_nxny_(sec, &nnx, &nny, &nnpnts, &nres, &nscan, &n_variable_dim, &variable_dim, &raw_variable_dim) 30 | gds = sec[3] 31 | 32 | if nny < 1 { 33 | return fprintf( /*stderr, */ "Sorry code does not handle variable ny yet") 34 | } 35 | 36 | /* 37 | if ((*lat = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 38 | return fatal_error("regular2ll memory allocation failed",""); 39 | } 40 | */ 41 | *lat = make([]double, nnpnts, nnpnts) 42 | /* 43 | if ((*lon = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 44 | return fatal_error("regular2ll memory allocation failed",""); 45 | } 46 | */ 47 | *lon = make([]double, nnpnts, nnpnts) 48 | 49 | /* now figure out the grid coordinates mucho silly grib specification */ 50 | 51 | basic_ang = GDS_LatLon_basic_ang(gds) 52 | sub_ang = GDS_LatLon_sub_ang(gds) 53 | if basic_ang != 0 { 54 | units = double(basic_ang) / double(sub_ang) 55 | } else { 56 | units = 0.000001 57 | } 58 | 59 | dlat = double(GDS_LatLon_dlat(gds)) * units 60 | dlon = double(GDS_LatLon_dlon(gds)) * units 61 | lat1 = double(GDS_LatLon_lat1(gds)) * units 62 | lat2 = double(GDS_LatLon_lat2(gds)) * units 63 | lon1 = double(GDS_LatLon_lon1(gds)) * units 64 | lon2 = double(GDS_LatLon_lon2(gds)) * units 65 | 66 | if lon1 < 0.0 || lon2 < 0.0 { 67 | return fatal_error("BAD grid definition lon < zero", "") 68 | } 69 | if lon1 > 360.0 || lon2 > 360.0 { 70 | return fatal_error("BAD grid definition lon >= 360", "") 71 | } 72 | if lat1 < -90.0 || lat2 < -90.0 || lat1 > 90.0 || lat2 > 90.0 { 73 | return fatal_error("BAD grid definition lat", "") 74 | } 75 | 76 | /* find S latitude and dy */ 77 | if GDS_Scan_y(nscan) { 78 | s = lat1 79 | n = lat2 80 | } else { 81 | s = lat2 82 | n = lat1 83 | } 84 | if s > n { 85 | return fatal_error("lat-lon grid: lat1 and lat2 inconsistent with scan order", "") 86 | } 87 | 88 | if nny > 1 { 89 | dy = (n - s) / double(nny-1) 90 | if nres&16 != 0 { /* lat increment is valid */ 91 | if fabs(dy-dlat) > 0.001 { 92 | return fatal_error("lat-lon grid: dlat is inconsistent", "") 93 | } 94 | } 95 | } else { 96 | dy = 0.0 97 | } 98 | // fprintf(stderr,">>> geo: dy %lf dlat %lf nres %d has dy %d has dx %d\n", dy, dlat, nres, nres & 16, nres & 32); 99 | 100 | /* find W latitude and dx */ 101 | 102 | if GDS_Scan_row_rev(nscan) && (nny%2 == 0) && ((nres & 32) == 0) { 103 | //fatal_error("grib GDS ambiguity", "") 104 | } 105 | 106 | if GDS_Scan_x(nscan) { 107 | w = lon1 108 | e = lon2 109 | if GDS_Scan_row_rev(nscan) && ((nres & 32) == 0) { 110 | e = lon1 + (double(nnx)-1)*dlon 111 | } 112 | } else { 113 | w = lon2 114 | e = lon1 115 | if GDS_Scan_row_rev(nscan) && ((nres & 32) == 0) { 116 | w = lon1 - (double(nnx)-1)*dlon 117 | } 118 | } 119 | 120 | if e <= w { 121 | e += 360.0 122 | } 123 | if e-w > 360.0 { 124 | e -= 360.0 125 | } 126 | if w < 0 { 127 | w += 360.0 128 | e += 360.0 129 | } 130 | 131 | /* lat-lon should be in a WE:SN order */ 132 | 133 | if nnx > 0 && nny > 0 { /* non-thinned, potentially staggered grid */ 134 | /* put x[] and y[] values in lon[] and lat[] */ 135 | llat = *lat 136 | llon = *lon 137 | err := stagger(sec, nnpnts, llon, llat, &n_variable_dim, &variable_dim, &raw_variable_dim) 138 | if err != nil { 139 | return fatal_error_wrap(err, "geo: stagger problem", "") 140 | } 141 | 142 | if nnx > 1 { 143 | dx = (e - w) / (double(nnx) - 1) 144 | dx = fabs(dx) 145 | if (nres & 32) != 0 { /* lon increment is valid */ 146 | if fabs(dx-fabs(dlon)) > 0.001 { 147 | return fatal_error("lat-lon grid: dlon is inconsistent", "") 148 | } 149 | } 150 | } else { 151 | dx = 0.0 152 | } 153 | dy = fabs(dy) 154 | 155 | for j = 0; j < nnpnts; j++ { 156 | llon[j] = lon1 + llon[j]*dx 157 | // llon[j] = llon[j] >= 360.0 ? llon[j] - 360.0 : llon[j]; 158 | if llon[j] >= 360.0 { 159 | llon[j] = llon[j] - 360.0 160 | } 161 | 162 | // llon[j] = llon[j] < 0.0 ? llon[j] + 360.0 : llon[j]; 163 | if llon[j] < 0.0 { 164 | llon[j] = llon[j] + 360.0 165 | } 166 | llat[j] = lat1 + llat[j]*dy 167 | } 168 | return nil 169 | } 170 | 171 | /* must be thinned grid */ 172 | 173 | llat = *lat 174 | llatIndex := 0 175 | /* quasi-regular grid */ 176 | for j = 0; j < nny; j++ { 177 | for i = 0; i < unsigned_int(variable_dim[j]); i++ { 178 | llat[llatIndex] = s + double(j)*dy 179 | llatIndex++ 180 | } 181 | } 182 | 183 | llon = *lon 184 | llonIndex := 0 185 | /* quasi-regular grid */ 186 | for j = 0; j < nny; j++ { 187 | dx = (e - w) / double(variable_dim[j]-1) 188 | for i = 0; i < unsigned_int(variable_dim[j]); i++ { 189 | //*llon++ = w + i*dx >= 360.0 ? w + i*dx - 360.0: w + i*dx; 190 | if w+double(i)*dx >= 360.0 { 191 | llon[llonIndex] = w + double(i)*dx - 360.0 192 | } else { 193 | llon[llonIndex] = w + double(i)*dx 194 | } 195 | llonIndex++ 196 | } 197 | } 198 | return nil 199 | } /* end regular2ll() */ 200 | 201 | func rot_regular2ll(sec [][]unsigned_char, lat *[]double, lon *[]double) error { 202 | 203 | var gds []unsigned_char 204 | var units double 205 | var tlon, tlat []double 206 | var sp_lat, sp_lon, angle_rot double 207 | var sin_a, cos_a double 208 | var basic_ang, sub_ang int 209 | var i, npnts unsigned_int 210 | var a, b, r, pr, gr, pm, gm, glat, glon double 211 | 212 | /* get the lat-lon coordinates in rotated frame of referencee */ 213 | err := regular2ll(sec, lat, lon) 214 | if err != nil { 215 | return fatal_error_wrap(err, "Failed to execute regular2ll") 216 | } 217 | 218 | gds = sec[3] 219 | npnts = GB2_Sec3_npts(sec) 220 | 221 | basic_ang = GDS_LatLon_basic_ang(gds) 222 | sub_ang = GDS_LatLon_sub_ang(gds) 223 | if basic_ang != 0 { 224 | units = double(basic_ang) / double(sub_ang) 225 | } else { 226 | units = 0.000001 227 | } 228 | 229 | sp_lat = double(GDS_RotLatLon_sp_lat(gds)) * units 230 | sp_lon = double(GDS_RotLatLon_sp_lon(gds)) * units 231 | angle_rot = double(GDS_RotLatLon_rotation(gds)) * units 232 | 233 | a = (M_PI / 180.0) * (90.0 + sp_lat) 234 | b = (M_PI / 180.0) * sp_lon 235 | r = (M_PI / 180.0) * angle_rot 236 | 237 | sin_a = sin(a) 238 | cos_a = cos(a) 239 | 240 | tlat = *lat 241 | tlon = *lon 242 | tlat_index := 0 243 | tlon_index := 0 244 | for i = 0; i < npnts; i++ { 245 | pr = (M_PI / 180.0) * tlat[tlat_index] 246 | gr = -(M_PI / 180.0) * tlon[tlon_index] 247 | pm = asin(cos(pr) * cos(gr)) 248 | gm = atan2(cos(pr)*sin(gr), -sin(pr)) 249 | glat = (180.0 / M_PI) * (asin(sin_a*sin(pm) - cos_a*cos(pm)*cos(gm-r))) 250 | glon = -(180.0 / M_PI) * (-b + atan2(cos(pm)*sin(gm-r), sin_a*cos(pm)*cos(gm-r)+cos_a*sin(pm))) 251 | tlat[tlat_index] = glat 252 | tlat_index++ 253 | tlon[tlon_index] = glon 254 | tlon_index++ 255 | } 256 | return nil 257 | } 258 | 259 | func mercator2ll(sec [][]unsigned_char, lat *[]double, lon *[]double) error { 260 | 261 | var dx, dy, lat1, lat2, lon1, lon2 double 262 | var llat, llon []double 263 | var i, j unsigned_int 264 | var dlon, circum double 265 | 266 | var n, s, e, w, tmp, error_ double 267 | var gds []unsigned_char 268 | 269 | var nnx, nny unsigned_int 270 | var nres, nscan int 271 | var nnpnts unsigned_int 272 | 273 | var n_variable_dim int 274 | var variable_dim, raw_variable_dim []int 275 | 276 | get_nxny_(sec, &nnx, &nny, &nnpnts, &nres, &nscan, &n_variable_dim, &variable_dim, &raw_variable_dim) 277 | gds = sec[3] 278 | 279 | dy = GDS_Mercator_dy(gds) 280 | dx = GDS_Mercator_dx(gds) 281 | lat1 = GDS_Mercator_lat1(gds) 282 | lat2 = GDS_Mercator_lat2(gds) 283 | lon1 = GDS_Mercator_lon1(gds) 284 | lon2 = GDS_Mercator_lon2(gds) 285 | 286 | if lon1 < 0.0 || lon2 < 0.0 || lon1 > 360.0 || lon2 > 360.0 { 287 | return fatal_error("BAD GDS lon", "") 288 | } 289 | if lat1 < -90.0 || lat2 < -90.0 || lat1 > 90.0 || lat2 > 90.0 { 290 | return fatal_error("BAD GDS lat", "") 291 | } 292 | 293 | if GDS_Mercator_ori_angle(gds) != 0.0 { 294 | return fprintf("cannot handle non-zero mercator orientation angle %f\n", 295 | double(GDS_Mercator_ori_angle(gds))) 296 | } 297 | 298 | if nnx < 1 || nny < 1 { 299 | return fprintf("Sorry geo/mercator code does not handle variable nx/ny yet\n") 300 | } 301 | 302 | /* 303 | if ((*lat = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 304 | fatal_error("mercator2ll memory allocation failed",""); 305 | } 306 | if ((*lon = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 307 | fatal_error("mercator2ll memory allocation failed",""); 308 | } 309 | */ 310 | *lat = make([]double, nnpnts, nnpnts) 311 | *lon = make([]double, nnpnts, nnpnts) 312 | 313 | /* now figure out the grid coordinates mucho silly grib specification */ 314 | 315 | /* find S and N latitude */ 316 | if GDS_Scan_y(nscan) { 317 | s = lat1 318 | n = lat2 319 | } else { 320 | s = lat2 321 | n = lat1 322 | } 323 | if s > n { 324 | fatal_error("Mercator grid: lat1 and lat2", "") 325 | } 326 | 327 | /* find W and E longitude */ 328 | 329 | if ((nscan & 16) == 16) && (nny%2 == 0) && ((nres & 32) == 0) { 330 | fatal_error("grib GDS ambiguity", "") 331 | } 332 | 333 | if ((nscan & 16) == 16) && (nny%2 == 0) { 334 | fatal_error("more code needed to decode GDS", "") 335 | } 336 | 337 | if GDS_Scan_x(nscan) { 338 | w = lon1 339 | e = lon2 340 | } else { 341 | w = lon2 342 | e = lon1 343 | } 344 | if e <= w { 345 | e += 360.0 346 | } 347 | 348 | llat = *lat 349 | llon = *lon 350 | 351 | dlon = (e - w) / double(nnx-1) 352 | radius, err := radius_earth(sec) 353 | if err != nil { 354 | return fatal_error_wrap(err, "Failed to execute radius_earth") 355 | } 356 | circum = 2.0 * M_PI * radius * cos(double(GDS_Mercator_latD(gds))*(M_PI/180.0)) 357 | dx = dx * 360.0 / circum 358 | 359 | // dlon should be almost == to dx 360 | // replace dx by dlon to get end points to match 361 | 362 | if dx != 0.0 { 363 | error_ = fabs(dx-dlon) / fabs(dx) 364 | if error_ >= 0.001 { 365 | return fprintf("\n*** Mercator grid error: inconsistent d-longitude, radius and grid domain\n*** d-longitude from grid domain %f (used), d-longitude from dx %f (not used)\n", dlon, dx) 366 | } 367 | dx = dlon 368 | } 369 | 370 | s = log(tan((45 + s/2) * M_PI / 180)) 371 | n = log(tan((45 + n/2) * M_PI / 180)) 372 | dy = (n - s) / (double(nny) - 1) 373 | 374 | llat_index := 0 375 | for j = 0; j < nny; j++ { 376 | tmp = (atan(exp(s+double(j)*dy))*180/M_PI - 45) * 2 377 | for i = 0; i < nnx; i++ { 378 | llat[llat_index] = tmp 379 | llat_index++ 380 | } 381 | } 382 | 383 | for j = 0; j < nnx; j++ { 384 | if w+double(j)*dx >= 360.0 { 385 | llon[j] = w + double(j)*dx - 360.0 386 | } else { 387 | llon[j] = w + double(j)*dx 388 | } 389 | } 390 | for j = nnx; j < nnpnts; j++ { 391 | llon[j] = llon[j-nnx] 392 | } 393 | return nil 394 | } /* end mercator2ll() */ 395 | 396 | func polar2ll(sec [][]unsigned_char, llat *[]double, llon *[]double) error { 397 | 398 | var lat, lon []double 399 | var gds []unsigned_char 400 | 401 | var dx, dy, orient, de, de2, dr, tmp, xp, yp, h, lat1, lon1, dr2 double 402 | var di, dj, LatD double 403 | var ix, iy unsigned_int 404 | var nnx, nny unsigned_int 405 | var nres, nscan int 406 | var nnpnts unsigned_int 407 | var nx size_t 408 | 409 | var n_variable_dim int 410 | var variable_dim, raw_variable_dim []int 411 | 412 | get_nxny_(sec, &nnx, &nny, &nnpnts, &nres, &nscan, &n_variable_dim, &variable_dim, &raw_variable_dim) 413 | 414 | gds = sec[3] 415 | 416 | if nnx < 1 || nny < 1 { 417 | return fprintf("Sorry code does not handle variable nx/ny yet\n") 418 | } 419 | nx = size_t(nnx) /* size_t, multiplications will not overflow */ 420 | 421 | /* 422 | if ((*llat = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 423 | fatal_error("polar2ll memory allocation failed",""); 424 | } 425 | if ((*llon = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 426 | fatal_error("polar2ll memory allocation failed",""); 427 | } 428 | */ 429 | *llat = make([]double, nnpnts, nnpnts) 430 | *llat = make([]double, nnpnts, nnpnts) 431 | 432 | lat = *llat 433 | lon = *llon 434 | 435 | /* based on iplib */ 436 | 437 | lat1 = GDS_Polar_lat1(gds) * (M_PI / 180) 438 | lon1 = GDS_Polar_lon1(gds) 439 | orient = GDS_Polar_lov(gds) 440 | LatD = GDS_Polar_lad(gds) 441 | 442 | lon1 *= (M_PI / 180.0) 443 | orient *= (M_PI / 180.0) 444 | 445 | dy = GDS_Polar_dy(gds) 446 | dx = GDS_Polar_dx(gds) 447 | 448 | h = 1.0 449 | if GDS_Polar_sps(gds) { 450 | h = -1.0 451 | /* added 12/19/2008 WNE sps checkout */ 452 | orient -= M_PI 453 | } 454 | 455 | // removed 12/11 if (! (GDS_Scan_x(nscan))) dx = -dx; 456 | // removed 12/11 if (! (GDS_Scan_y(nscan))) dy = -dy; 457 | 458 | /* 60 probably becomes something else in grib2 */ 459 | /* vsm: from comment to grib2 polar template: 460 | "Grid length is in units of 10-3 m at the latitude specified by LaD" 461 | do use GDS_Polar_lad(gds) instead of 60? 462 | Do use fabs for southern hemisphere? 463 | */ 464 | 465 | radius, err := radius_earth(sec) 466 | if err != nil { 467 | return fatal_error_wrap(err, "Failed to execute radius_earth") 468 | } 469 | de = (1.0 + sin(fabs(LatD)*(M_PI/180.0))) * radius 470 | dr = de * cos(lat1) / (1 + h*sin(lat1)) 471 | 472 | xp = -h * sin(lon1-orient) * dr / dx 473 | yp = cos(lon1-orient) * dr / dy 474 | 475 | // added 12/11 476 | if !(GDS_Scan_y(nscan)) { 477 | yp = yp - double(nny) + 1 478 | } 479 | if !(GDS_Scan_x(nscan)) { 480 | xp = xp - double(nnx) + 1 481 | } 482 | 483 | de2 = de * de 484 | //#pragma omp parallel for private(iy,ix,di,dj,dr2,tmp) 485 | for iy = 0; iy < nny; iy++ { 486 | for ix = 0; ix < nnx; ix++ { 487 | di = (double(ix) - xp) * dx 488 | dj = (double(iy) - yp) * dy 489 | dr2 = di*di + dj*dj 490 | if dr2 < de2*1e-6 { 491 | lon[ix+iy*unsigned_int(nx)] = 0.0 492 | lat[ix+iy*unsigned_int(nx)] = h * 90.0 493 | } else { 494 | tmp = (orient + h*atan2(di, -dj)) * (180.0 / M_PI) 495 | if tmp < 0.0 { 496 | tmp += 360.0 497 | } 498 | if tmp > 360.0 { 499 | tmp -= 360.0 500 | } 501 | lon[ix+iy*unsigned_int(nx)] = tmp 502 | lat[ix+iy*unsigned_int(nx)] = h * asin((de2-dr2)/(de2+dr2)) * (180.0 / M_PI) 503 | } 504 | } 505 | } 506 | return nil 507 | } 508 | 509 | func lambert2ll(sec [][]unsigned_char, llat *[]double, llon *[]double) error { 510 | 511 | var n double 512 | var lat, lon []double 513 | 514 | var dx, dy, lat1r, lon1r, lon2d, lon2r, latin1r, latin2r double 515 | var lond, latd, d_lon double 516 | var f, rho, rhoref, theta, startx, starty double 517 | var nnx, nny unsigned_int 518 | var nres, nscan int 519 | var x, y, tmp double 520 | var gds []unsigned_char 521 | var latDr double 522 | var earth_radius double 523 | var j, nnpnts unsigned_int 524 | 525 | var n_variable_dim int 526 | var variable_dim, raw_variable_dim []int 527 | 528 | get_nxny_(sec, &nnx, &nny, &nnpnts, &nres, &nscan, &n_variable_dim, &variable_dim, &raw_variable_dim) 529 | 530 | if nnx < 1 || nny < 1 { 531 | return fprintf("Sorry code does not handle variable nx/ny yet\n") 532 | } 533 | 534 | earth_radius, err := radius_earth(sec) 535 | if err != nil { 536 | return fatal_error_wrap(err, "Failed to execute radius_earth") 537 | } 538 | gds = sec[3] 539 | dy = GDS_Lambert_dy(gds) 540 | dx = GDS_Lambert_dx(gds) 541 | lat1r = GDS_Lambert_La1(gds) * (M_PI / 180.0) 542 | lon1r = GDS_Lambert_Lo1(gds) * (M_PI / 180.0) 543 | lon2d = GDS_Lambert_Lov(gds) 544 | lon2r = lon2d * (M_PI / 180.0) 545 | latin1r = GDS_Lambert_Latin1(gds) * (M_PI / 180.0) 546 | latin2r = GDS_Lambert_Latin2(gds) * (M_PI / 180.0) 547 | 548 | // fix for theta start value crossing 0 longitude 549 | // if ((lon1r - lon2r) > 0) lon2r = lon2r + 2*M_PI; 550 | 551 | // 552 | // Latitude of "false origin" where scales are defined. 553 | // It is used to estimate "reference_R", rhoref. 554 | // Often latDr == latin1r == latin2r and non-modified code is true and works fine. 555 | // But could be different if intersection latitudes latin1r and latin2r are different. 556 | // Usually latDr must be latin1r <= latDr <= latin2r, other could be strange. 557 | // 558 | latDr = GDS_Lambert_LatD(gds) * (M_PI / 180.0) 559 | 560 | if lon1r < 0 { 561 | return fatal_error("bad GDS, lon1r < 0.0", "") 562 | } 563 | 564 | if fabs(latin1r-latin2r) < 1E-09 { 565 | n = sin(latin1r) 566 | } else { 567 | n = log(cos(latin1r)/cos(latin2r)) / 568 | log(tan(M_PI_4+latin2r/2.0)/tan(M_PI_4+latin1r/2.0)) 569 | } 570 | 571 | f = (cos(latin1r) * pow(tan(M_PI_4+latin1r/2.0), n)) / n 572 | 573 | rho = earth_radius * f * pow(tan(M_PI_4+lat1r/2.0), -n) 574 | // old rhoref = earth_radius * f * pow(tan(M_PI_4 + latin1r/2.0),-n); 575 | rhoref = earth_radius * f * pow(tan(M_PI_4+latDr/2.0), -n) 576 | 577 | // 2/2009 .. new code 578 | d_lon = lon1r - lon2r 579 | if d_lon > M_PI { 580 | d_lon -= 2 * M_PI 581 | } 582 | if d_lon < -M_PI { 583 | d_lon += 2 * M_PI 584 | } 585 | theta = n * d_lon 586 | // 2/2009 theta = n * (lon1r - lon2r); 587 | 588 | startx = rho * sin(theta) 589 | starty = rhoref - rho*cos(theta) 590 | 591 | /* 592 | if ((*llat = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 593 | fatal_error("lambert2ll memory allocation failed",""); 594 | } 595 | if ((*llon = (double *) malloc(((size_t) nnpnts) * sizeof(double))) == NULL) { 596 | fatal_error("lambert2ll memory allocation failed",""); 597 | } 598 | */ 599 | *llat = make([]double, nnpnts, nnpnts) 600 | *llat = make([]double, nnpnts, nnpnts) 601 | 602 | lat = *llat 603 | lon = *llon 604 | 605 | /* put x[] and y[] values in lon[] and lat[] */ 606 | if err := stagger(sec, nnpnts, lon, lat, &n_variable_dim, &variable_dim, &raw_variable_dim); err != nil { 607 | fatal_error_wrap(err, "geo: stagger problem") 608 | } 609 | 610 | dx = fabs(dx) 611 | dy = fabs(dy) 612 | 613 | // #pragma omp parallel for private(j,x,y,tmp,theta,rho,lond,latd) 614 | for j = 0; j < nnpnts; j++ { 615 | y = starty + lat[j]*dy 616 | x = startx + lon[j]*dx 617 | tmp = rhoref - y 618 | theta = atan(x / tmp) 619 | rho = sqrt(x*x + tmp*tmp) 620 | //rho = n > 0 ? rho : -rho; 621 | if n > 0 { 622 | rho = rho 623 | } else { 624 | rho = -rho 625 | } 626 | lond = lon2d + todegrees(theta/n) 627 | latd = todegrees(2.0*atan(pow(earth_radius*f/rho, 1.0/n)) - M_PI_2) 628 | // lond = lond >= 360.0 ? lond - 360.0 : lond; 629 | if lond >= 360.0 { 630 | lond = lond - 360.0 631 | } 632 | // lond = lond < 0.0 ? lond + 360.0 : lond; 633 | if lond < 0.0 { 634 | lond = lond + 360.0 635 | } 636 | lon[j] = lond 637 | lat[j] = latd 638 | } 639 | return nil 640 | } /* end lambert2ll() */ 641 | --------------------------------------------------------------------------------