From e91746893da2f439ebefed14a6f344d52a010818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20GIRAUD?= Date: Fri, 21 Jun 2024 13:22:42 +0200 Subject: [PATCH 1/2] ran various linters --- griblib/bitgroup.go | 6 +- griblib/calculations.go | 6 +- griblib/data2.go | 4 +- griblib/data3.go | 16 +- griblib/exports.go | 7 +- griblib/filters.go | 2 +- griblib/gribtest/performance_test.go | 5 +- griblib/gribtest/pngExport_test.go | 12 +- griblib/gribtest/sections_test.go | 6 +- griblib/grids.go | 24 +-- griblib/pngExport.go | 38 +++-- griblib/products.go | 16 +- griblib/reducer.go | 11 +- griblib/sections.go | 209 ++++++++++++++------------- griblib/specs.go | 136 ++++++++--------- internal/reader/bitreader.go | 4 - main.go | 22 ++- 17 files changed, 283 insertions(+), 241 deletions(-) diff --git a/griblib/bitgroup.go b/griblib/bitgroup.go index 6e761c0..8f15155 100644 --- a/griblib/bitgroup.go +++ b/griblib/bitgroup.go @@ -19,13 +19,13 @@ func (bitGroup *bitGroupParameter) zeroGroup() []int64 { func (bitGroup *bitGroupParameter) readData(bitReader *reader.BitReader) ([]int64, error) { var err error if bitGroup.Width != 0 { - uintArray, err := bitReader.ReadUintsBlock(int(bitGroup.Width), int64(bitGroup.Length), false) + uintArray, err2 := bitReader.ReadUintsBlock(int(bitGroup.Width), int64(bitGroup.Length), false) output := make([]int64, len(uintArray)) for idx, val := range uintArray { output[idx] = int64(val) } - return output, err + return output, err2 } return bitGroup.zeroGroup(), err @@ -43,7 +43,7 @@ func checkLengths(bitGroups []bitGroupParameter, dataLength int) error { } if totBit/8 > int(dataLength) { - return fmt.Errorf("Checksum err %d - %d", dataLength, totBit/8) + return fmt.Errorf("checksum err %d - %d", dataLength, totBit/8) } return nil diff --git a/griblib/calculations.go b/griblib/calculations.go index 22ec87a..c001ab3 100644 --- a/griblib/calculations.go +++ b/griblib/calculations.go @@ -5,7 +5,7 @@ import ( "reflect" ) -// AverageValueBasic takes a GeoFilter, Grid0 and data to calculate the average value within that area. +// AverageValueBasic takes a GeoFilter, Grid0 and data to calculate the average value within that area. // See GeoFilter for how to define an area func AverageValueBasic(filter GeoFilter, grid0 *Grid0, data []float64) (float64, error) { startNi, stopNi, startNj, stopNj := StartStopIndexes(filter, *grid0) @@ -23,9 +23,9 @@ func AverageValueBasic(filter GeoFilter, grid0 *Grid0, data []float64) (float64, func AverageValue(filter GeoFilter, message *Message) (float64, error) { grid0, ok := message.Section3.Definition.(*Grid0) - data := message.Section7.Data + data := message.Section7.Data if ok { return AverageValueBasic(filter, grid0, data) } - return -1, fmt.Errorf("grid not of wanted type (wanted Grid0), was %v.", reflect.TypeOf(message.Section3.Definition)) + return -1, fmt.Errorf("grid not of wanted type (wanted Grid0), was %v", reflect.TypeOf(message.Section3.Definition)) } diff --git a/griblib/data2.go b/griblib/data2.go index 7371c99..5d901c6 100644 --- a/griblib/data2.go +++ b/griblib/data2.go @@ -194,8 +194,8 @@ func ParseData2(dataReader io.Reader, dataLength int, template *Data2) ([]float6 // Test to see if the group widths and lengths are consistent with number of // values, and length of section 7. // - if err := checkLengths(bitGroups, dataLength); err != nil { - return nil, err + if err2 := checkLengths(bitGroups, dataLength); err2 != nil { + return nil, err2 } // diff --git a/griblib/data3.go b/griblib/data3.go index 174da9e..66a4d38 100644 --- a/griblib/data3.go +++ b/griblib/data3.go @@ -56,19 +56,19 @@ func (template *Data3) extractSpacingDifferentialValues(bitReader *reader.BitRea var err error ival1, err = bitReader.ReadInt(rc) if err != nil { - return minsd, ival1, ival2, fmt.Errorf("Spacial differencing Value 1: %s", err.Error()) + return minsd, ival1, ival2, fmt.Errorf("spacial differencing Value 1: %s", err.Error()) } if template.SpatialOrderDifference == 2 { ival2, err = bitReader.ReadInt(rc) if err != nil { - return minsd, ival1, ival2, fmt.Errorf("Spacial differencing Value 2: %s", err.Error()) + return minsd, ival1, ival2, fmt.Errorf("spacial differencing Value 2: %s", err.Error()) } } minsd, err = bitReader.ReadInt(rc) if err != nil { - return minsd, ival1, ival2, fmt.Errorf("Spacial differencing Reference: %s", err.Error()) + return minsd, ival1, ival2, fmt.Errorf("spacial differencing Reference: %s", err.Error()) } } @@ -91,7 +91,7 @@ func ParseData3(dataReader io.Reader, dataLength int, template *Data3) ([]float6 // minsd, ival1, ival2, err := template.extractSpacingDifferentialValues(bitReader) if err != nil { - return nil, fmt.Errorf("Spacial differencing Value 1: %s", err.Error()) + return nil, fmt.Errorf("spacial differencing Value 1: %s", err.Error()) } // @@ -99,15 +99,15 @@ func ParseData3(dataReader io.Reader, dataLength int, template *Data3) ([]float6 // bitGroups, err := template.extractBitGroupParameters(bitReader) if err != nil { - return nil, fmt.Errorf("Groups: %s", err.Error()) + return nil, fmt.Errorf("groups: %s", err.Error()) } // // Test to see if the group widths and lengths are consistent with number of // values, and length of section 7. // - if err := checkLengths(bitGroups, dataLength); err != nil { - return nil, fmt.Errorf("Check length: %s", err.Error()) + if err2 := checkLengths(bitGroups, dataLength); err2 != nil { + return nil, fmt.Errorf("check length: %s", err2.Error()) } // @@ -115,7 +115,7 @@ func ParseData3(dataReader io.Reader, dataLength int, template *Data3) ([]float6 // section7Data, ifldmiss, err := template.extractData(bitReader, bitGroups) if err != nil { - return nil, fmt.Errorf("Data extract: %s", err.Error()) + return nil, fmt.Errorf("data extract: %s", err.Error()) } // diff --git a/griblib/exports.go b/griblib/exports.go index 52c8b33..a445071 100644 --- a/griblib/exports.go +++ b/griblib/exports.go @@ -65,7 +65,10 @@ func export(m *Message) { // json print js, _ := json.Marshal(m) var out bytes.Buffer - json.Compact(&out, js) - out.WriteTo(os.Stdout) + err := json.Compact(&out, js) + if err != nil { + log.Printf("Error compacting json: %v\n", err) + } + _, _ = out.WriteTo(os.Stdout) log.Println("") } diff --git a/griblib/filters.go b/griblib/filters.go index c0b6e12..bedbd70 100644 --- a/griblib/filters.go +++ b/griblib/filters.go @@ -13,7 +13,7 @@ import ( // note that latitude 90 is considered lesser than latitude 85 in calculations. // an example for a valid filter is // -// filter := griblib.GeoFilter{MinLong: 10_000_000, MinLat: 85_000_000, MaxLat: 70_000_000, MaxLong: 15_000_000} +// filter := griblib.GeoFilter{MinLong: 10_000_000, MinLat: 85_000_000, MaxLat: 70_000_000, MaxLong: 15_000_000} // // note than MinLat has higher integer value than MaxLat type GeoFilter struct { diff --git a/griblib/gribtest/performance_test.go b/griblib/gribtest/performance_test.go index 031e12b..ebd244b 100644 --- a/griblib/gribtest/performance_test.go +++ b/griblib/gribtest/performance_test.go @@ -13,6 +13,9 @@ func BenchmarkReadMessages(b *testing.B) { if err != nil { b.Fatalf("Could not open test-file %v", err) } - griblib.ReadMessages(f) + _, err = griblib.ReadMessages(f) + if err != nil { + b.Fatalf("Could not read messages %v", err) + } } } diff --git a/griblib/gribtest/pngExport_test.go b/griblib/gribtest/pngExport_test.go index 2cba7b7..b1fcc54 100644 --- a/griblib/gribtest/pngExport_test.go +++ b/griblib/gribtest/pngExport_test.go @@ -10,10 +10,18 @@ import ( ) func beforeTests(t *testing.T) func(t *testing.T) { - os.MkdirAll("testoutput", os.ModePerm) + err := os.MkdirAll("testoutput", 0750) + if err != nil { + t.Errorf("Could not create testoutput directory: %v", err) + t.Fail() + } return func(t *testing.T) { - os.RemoveAll("testoutput") + err2 := os.RemoveAll("testoutput") + if err2 != nil { + t.Errorf("Could not remove testoutput directory: %v", err2) + t.Fail() + } } } diff --git a/griblib/gribtest/sections_test.go b/griblib/gribtest/sections_test.go index bcc537b..4b79cad 100644 --- a/griblib/gribtest/sections_test.go +++ b/griblib/gribtest/sections_test.go @@ -4,6 +4,7 @@ import ( "bytes" "encoding/binary" "io" + "log" "testing" "github.com/nilsmagnus/grib/griblib" @@ -64,7 +65,10 @@ func Test_read_section1(t *testing.T) { func toIoReader(data interface{}) (reader io.Reader) { var binBuf bytes.Buffer - binary.Write(&binBuf, binary.BigEndian, data) + err := binary.Write(&binBuf, binary.BigEndian, data) + if err != nil { + log.Printf("Error writing to buffer: %s", err.Error()) + } reader = bytes.NewReader(binBuf.Bytes()) diff --git a/griblib/grids.go b/griblib/grids.go index e34869a..62c4c10 100644 --- a/griblib/grids.go +++ b/griblib/grids.go @@ -14,24 +14,24 @@ func fixNegLatLon(num int32) int32 { return num } -//ScaledValue specifies the scale of a value +// ScaledValue specifies the scale of a value type ScaledValue struct { Scale uint8 `json:"scale"` Value uint32 `json:"value"` } -//BasicAngle specifies the angle of a grid +// BasicAngle specifies the angle of a grid type BasicAngle struct { BasicAngle uint32 `json:"basicAngle"` BasicAngleSub uint32 `json:"basicAngleSub"` } -//Grid is an interface for all grids. +// Grid is an interface for all grids. type Grid interface { Export() map[string]string } -//ReadGrid reads grid from binary input to the grid-number specified by templateNumber +// ReadGrid reads grid from binary input to the grid-number specified by templateNumber func ReadGrid(f io.Reader, templateNumber uint16) (Grid, error) { var err error var g Grid @@ -82,7 +82,7 @@ func ReadGrid(f io.Reader, templateNumber uint16) (Grid, error) { return g, err } -//GridHeader is a common header in all grids +// GridHeader is a common header in all grids type GridHeader struct { EarthShape uint8 `json:"earthShape"` SphericalRadius ScaledValue `json:"sphericalRadius"` @@ -90,14 +90,14 @@ type GridHeader struct { MinorAxis ScaledValue `json:"minorAxis"` } -//Export gridheader to a map[string]string +// Export gridheader to a map[string]string func (h *GridHeader) Export() (d map[string]string) { return map[string]string{ "earth": EarthShapeDescription(int(h.EarthShape)), } } -//Grid0 Definition Template 3.0: Latitude/longitude (or equidistant cylindrical, or Plate Carree) +// Grid0 Definition Template 3.0: Latitude/longitude (or equidistant cylindrical, or Plate Carree) type Grid0 struct { //Name := "Latitude/longitude (or equidistant cylindrical, or Plate Carree) " GridHeader @@ -114,7 +114,7 @@ type Grid0 struct { ScanningMode uint8 `json:"scanningMode"` } -//Export Grid0 to a map[string]string +// Export Grid0 to a map[string]string func (h *Grid0) Export() map[string]string { return map[string]string{ "earth": EarthShapeDescription(int(h.EarthShape)), @@ -132,7 +132,7 @@ func (h *Grid0) Export() map[string]string { } } -//Grid10 Definition Template 3.10: Mercator +// Grid10 Definition Template 3.10: Mercator type Grid10 struct { //name := "Mercator" GridHeader @@ -150,7 +150,7 @@ type Grid10 struct { Dj int32 `json:"dj"` } -//Grid20 Definition Template 3.20: Polar stereographic projection +// Grid20 Definition Template 3.20: Polar stereographic projection type Grid20 struct { //name = "Polar stereographic projection "; GridHeader @@ -167,7 +167,7 @@ type Grid20 struct { ScanningMode uint8 `json:"scanningMode"` } -//Grid30 Definition Template 3.30: Lambert conformal +// Grid30 Definition Template 3.30: Lambert conformal type Grid30 struct { //name = "Polar stereographic projection "; GridHeader @@ -207,7 +207,7 @@ type Grid40 struct { // Grid90 Definition Template 3.90: Space view perspective or orthographic // FIXME: implement properly -//Grid90 +// Grid90 type Grid90 struct { //name = "Space view perspective or orthographic "; GridHeader diff --git a/griblib/pngExport.go b/griblib/pngExport.go index 9b87ca7..9a6ce67 100644 --- a/griblib/pngExport.go +++ b/griblib/pngExport.go @@ -18,7 +18,10 @@ func ExportMessagesAsPngs(messages []*Message) { if err != nil { log.Printf("Message could not be converted to image: %v\n", err) } else { - writeImageToFilename(dataImage, imageFileName(i, message)) + err2 := writeImageToFilename(dataImage, imageFileName(i, message)) + if err2 != nil { + log.Printf("Image could not be written to file: %v\n", err2) + } } } } @@ -46,9 +49,12 @@ func writeImageToFilename(img image.Image, name string) error { return err } - if err := png.Encode(f, img); err != nil { - f.Close() - return err + if err2 := png.Encode(f, img); err2 != nil { + err3 := f.Close() + if err3 != nil { + log.Printf("Error closing file: %v\n", err3) + } + return err2 } if err := f.Close(); err != nil { @@ -62,7 +68,7 @@ func imageFromMessage(message *Message) (image.Image, error) { grid0, ok := message.Section3.Definition.(*Grid0) if !ok { - err := fmt.Errorf("Currently not supporting definition of type %s ", reflect.TypeOf(message.Section3.Definition)) + err := fmt.Errorf("currently not supporting definition of type %s ", reflect.TypeOf(message.Section3.Definition)) return nil, err } @@ -92,16 +98,6 @@ func imageFromMessage(message *Message) (image.Image, error) { return rgbaImage, nil } -// returns a number between 0 and 255 -func blueValue(value float64, maxValue float64, minValue float64) uint8 { - //value = value - 273 - if value < 0 { - percentOfMaxValue := (math.Abs(value) + math.Abs(minValue)) / (math.Abs(maxValue) + math.Abs(minValue)) - return uint8(percentOfMaxValue * 255.0) - } - return 0 -} - // RedValue returns a number between 0 and 255 func RedValue(value float64, maxValue float64, minValue float64) uint8 { //value = value - 273 @@ -113,14 +109,14 @@ func RedValue(value float64, maxValue float64, minValue float64) uint8 { } func MaxMin(float64s []float64) (float64, float64) { - max, min := -9999999.0, 999999.0 + biggest, smallest := -9999999.0, 999999.0 for _, v := range float64s { - if v > max { - max = v + if v > biggest { + biggest = v } - if v < min { - min = v + if v < smallest { + smallest = v } } - return max, min + return biggest, smallest } diff --git a/griblib/products.go b/griblib/products.go index 8344f62..e4302e0 100644 --- a/griblib/products.go +++ b/griblib/products.go @@ -17,7 +17,7 @@ type Product0 struct { SecondSurface Surface `json:"secondSurface"` } -//Product1 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-1.shtml +// Product1 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-1.shtml type Product1 struct { Product0 EnsembleForecastType uint8 `json:"ensembleForecastType"` @@ -25,14 +25,14 @@ type Product1 struct { ForecastInEnsembleCount uint8 `json:"forecastInEnsembleCount"` } -//Product2 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-2.shtml +// Product2 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-2.shtml type Product2 struct { Product0 DerivedForecast uint8 `json:"derivedForecast"` ForecastInEnsembleCount uint8 `json:"forecastInEnsembleCount"` } -//Product5 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-5.shtml +// Product5 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-5.shtml type Product5 struct { Product0 ForecastProbabilityNumber uint8 `json:"forecastProbabilityNumber"` @@ -44,18 +44,18 @@ type Product5 struct { ScaleValueUpperLimit uint32 `json:"scaleValueUpperLimit"` } -//Product6 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-6.shtml +// Product6 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-6.shtml type Product6 struct { Product0 PercentileValue uint8 `json:"percentileValue"` // 0-100 } -//Product7 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-7.shtml +// Product7 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-7.shtml type Product7 struct { Product0 } -//Product8 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-8.shtml +// Product8 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_temp4-8.shtml type Product8 struct { Product0 Time Time `json:"time"` @@ -66,7 +66,7 @@ type Product8 struct { AdditionalTimeRangeSpecifications []TimeRangeSpecification `json:"additionalTimeRangeSpecifications"` // 71-n } -//TimeRangeSpecification describes timerange for products +// TimeRangeSpecification describes timerange for products type TimeRangeSpecification struct { StatisticalFieldCalculationProcess uint8 `json:"statisticalFieldCalculationProcess"` // 47 IncrementBetweenSuccessiveFieldsType uint8 `json:"incrementBetweenSuccessiveFieldsType"` // 48 @@ -76,7 +76,7 @@ type TimeRangeSpecification struct { TimeIncrementBetweenSuccessiveField uint32 `json:"timeIncrementBetweenSuccessiveField"` // 55-58 } -//Surface describes a surface for a product, see http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-5.shtml +// Surface describes a surface for a product, see http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_table4-5.shtml type Surface struct { Type uint8 `json:"type"` // type 220: Planetary Boundary Layer Scale uint8 `json:"scale"` diff --git a/griblib/reducer.go b/griblib/reducer.go index 1b12d3f..aae80b3 100644 --- a/griblib/reducer.go +++ b/griblib/reducer.go @@ -7,7 +7,7 @@ import ( "strings" ) -//Reduce the file in readseeker with the given options, omitting all other products and areas +// Reduce the file in readseeker with the given options, omitting all other products and areas func Reduce(readSeeker io.Reader, options Options, content chan []byte, end chan bool) { if options.Discipline == -1 { log.Println("No disciplines defined for reduce.") @@ -42,7 +42,14 @@ func Reduce(readSeeker io.Reader, options Options, content chan []byte, end chan content <- messageSection0Bytes content <- messageContentBytes } else { - readSeeker.Read(make([]byte, int64(section0.MessageLength)-16)) + length := int64(section0.MessageLength) - 16 + bytesRead, err2 := readSeeker.Read(make([]byte, length)) + if int64(bytesRead) != length { + log.Printf("bytesRead: %v, length: %v", bytesRead, length) + } + if err2 != nil { + log.Printf("read3 err: %v", err2.Error()) + } } } diff --git a/griblib/sections.go b/griblib/sections.go index 4d90351..3456264 100644 --- a/griblib/sections.go +++ b/griblib/sections.go @@ -9,7 +9,7 @@ import ( "strings" ) -//Message is the entire message for a data-layer +// Message is the entire message for a data-layer type Message struct { Section0 Section0 Section1 Section1 @@ -21,7 +21,7 @@ type Message struct { Section7 Section7 } -//Options is used to filter messages. +// Options is used to filter messages. type Options struct { Operation string `json:"operation"` Discipline int `json:"discipline"` // -1 means all disciplines @@ -50,8 +50,8 @@ func (message Message) Data() []float64 { return message.Section7.Data } -//ReadMessages reads at most n first messages from gribFile -//if an error occurs, the read messages and the error is returned +// ReadNMessages reads at most n first messages from gribFile +// if an error occurs, the read messages and the error is returned func ReadNMessages(gribFile io.Reader, n int) ([]*Message, error) { messages := make([]*Message, 0) @@ -72,7 +72,7 @@ func ReadNMessages(gribFile io.Reader, n int) ([]*Message, error) { } } -//ReadMessages reads all message from gribFile +// ReadMessages reads all message from gribFile func ReadMessages(gribFile io.Reader) ([]*Message, error) { messages := make([]*Message, 0) @@ -90,7 +90,7 @@ func ReadMessages(gribFile io.Reader) ([]*Message, error) { } } -//ReadMessage reads the actual messages from a gribfile-reader (io.Reader from either file, http or any other io.Reader) +// ReadMessage reads the actual messages from a gribfile-reader (io.Reader from either file, http or any other io.Reader) func ReadMessage(gribFile io.Reader) (*Message, error) { message := Message{} @@ -159,7 +159,7 @@ func readMessage(gribFile io.Reader, section0 Section0) (*Message, error) { // end-section, return return &message, nil default: - err = fmt.Errorf("Unknown section number %d (Something bad with parser or files)", sectionHead.Number) + err = fmt.Errorf("unknown section number %d (Something bad with parser or files)", sectionHead.Number) } if err != nil { return &message, err @@ -174,13 +174,14 @@ func readMessage(gribFile io.Reader, section0 Section0) (*Message, error) { // This section serves to identify the start of the record in a human readable form, indicate the total length of the message, // and indicate the Edition number of GRIB used to construct or encode the message. For GRIB2, this section is always 16 octets // long. -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | 'GRIB' (Coded according to the International Alphabet Number 5) -// | 5-6 | reserved -// | 7 | Discipline (From Table 0.0) -// | 8 | Edition number - 2 for GRIB2 -// | 9-16 | Total length of GRIB message in octets (All sections); +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | 'GRIB' (Coded according to the International Alphabet Number 5) +// | 5-6 | reserved +// | 7 | Discipline (From Table 0.0) +// | 8 | Edition number - 2 for GRIB2 +// | 9-16 | Total length of GRIB message in octets (All sections); type Section0 struct { Indicator uint32 `json:"indicator"` Reserved uint16 `json:"reserved"` @@ -189,7 +190,7 @@ type Section0 struct { MessageLength uint64 `json:"messageLength"` } -//ReadSection0 reads Section0 from an io.reader +// ReadSection0 reads Section0 from an io.reader func ReadSection0(reader io.Reader) (section0 Section0, err error) { section0.Indicator = 255 err = binary.Read(reader, binary.BigEndian, §ion0) @@ -199,32 +200,33 @@ func ReadSection0(reader io.Reader) (section0 Section0, err error) { if section0.Indicator == Grib { if section0.Edition != SupportedGribEdition { - return section0, fmt.Errorf("Unsupported grib edition %d", section0.Edition) + return section0, fmt.Errorf("unsupported grib edition %d", section0.Edition) } } else { - return section0, fmt.Errorf("Unsupported grib indicator %d", section0.Indicator) + return section0, fmt.Errorf("unsupported grib indicator %d", section0.Indicator) } return } -//SectionHead is the common header for each section1-8 -// | Octet Number | Content -// ----------------------------------------------------------- -// | 1-4 | Length of the section in octets (21 or N) -// | 5 | Number of the section (1) +// SectionHead is the common header for each section1-8 +// +// | Octet Number | Content +// ----------------------------------------------------------- +// | 1-4 | Length of the section in octets (21 or N) +// | 5 | Number of the section (1) type SectionHead struct { ByteLength uint32 `json:"byteLength"` Number uint8 `json:"number"` } -//ReadSectionHead is poorly documented other than code +// ReadSectionHead is poorly documented other than code func ReadSectionHead(section io.Reader) (head SectionHead, err error) { var length uint32 err = binary.Read(section, binary.BigEndian, &length) if err != nil { - return head, fmt.Errorf("Read of Length failed: %s", err.Error()) + return head, fmt.Errorf("read of Length failed: %s", err.Error()) } if length == EndSectionLength { return SectionHead{ @@ -244,12 +246,12 @@ func ReadSectionHead(section io.Reader) (head SectionHead, err error) { }, nil } -//SectionNumber returns the number of the sectionhead +// SectionNumber returns the number of the sectionhead func (s SectionHead) SectionNumber() uint8 { return s.Number } -//ContentLength returns the binary length of the sectionhead +// ContentLength returns the binary length of the sectionhead func (s SectionHead) ContentLength() int { return int(s.ByteLength) - binary.Size(s) } @@ -258,15 +260,16 @@ func (s SectionHead) String() string { return fmt.Sprint("Section ", s.Number) } -//Time is the time of section 1 -// | Octet Number | Content -// --------------------------------- -// | 13-14 | Year (4 digits) -// | 15 | Month -// | 16 | Day -// | 17 | Hour -// | 18 | Minute -// | 19 | Second +// Time is the time of section 1 +// +// | Octet Number | Content +// --------------------------------- +// | 13-14 | Year (4 digits) +// | 15 | Month +// | 16 | Day +// | 17 | Hour +// | 18 | Minute +// | 19 | Second type Time struct { Year uint16 `json:"year"` // year Month uint8 `json:"month"` // month + 1 @@ -318,17 +321,18 @@ type Section1 struct { Type uint8 `json:"type"` // data type, Table 1.4, value 1 is forecast products } -//ReadSection1 is poorly documented other than code +// ReadSection1 is poorly documented other than code func ReadSection1(f io.Reader, length int) (section Section1, err error) { return section, binary.Read(f, binary.BigEndian, §ion) } // Section2 is the Local Use section http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_sect2.shtml -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | Length of the section in octets (N) -// | 5 | Number of the section (2) -// | 6-N | Local Use +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | Length of the section in octets (N) +// | 5 | Number of the section (2) +// | 6-N | Local Use // // Center=7 (NCEP), subcenter=14(NWS Meteorological Development Laboratory (MDL)) used octet 6 to indicate which local use table // to use. For MDL, octet 6=1 indicates use: "MDL Template 2.1" @@ -336,7 +340,7 @@ type Section2 struct { LocalUse []uint8 `json:"localUse"` } -//ReadSection2 is for "Local use" +// ReadSection2 is for "Local use" func ReadSection2(f io.Reader, len int) (section Section2, err error) { section.LocalUse = make([]uint8, len) return section, read(f, §ion.LocalUse) @@ -344,18 +348,19 @@ func ReadSection2(f io.Reader, len int) (section Section2, err error) { // Section3 is the Grid Definition section http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_sect3.shtml // It contains information of the grid(earth shape, long, lat, etc) -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | Length of the section in octets (nn) -// | 5 | Number of the section (3) -// | 6 | Source of grid definition (See Table 3.0) (See note 1 below) -// | 7-10 | Number of data points -// | 11 | Number of octets for optional list of numbers defining number of points (See note 2 below) -// | 12 | Interpetation of list of numbers defining number of points (See Table 3.11) -// | 13-14 | Grid definition template number (= N) (See Table 3.1) -// | 15-xx | Grid definition template (See Template 3.N, where N is the grid definition template -// | | number given in octets 13-14) -// | [xx+1]-nn | Optional list of numbers defining number of points (See notes 2, 3, and 4 below) +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | Length of the section in octets (nn) +// | 5 | Number of the section (3) +// | 6 | Source of grid definition (See Table 3.0) (See note 1 below) +// | 7-10 | Number of data points +// | 11 | Number of octets for optional list of numbers defining number of points (See note 2 below) +// | 12 | Interpetation of list of numbers defining number of points (See Table 3.11) +// | 13-14 | Grid definition template number (= N) (See Table 3.1) +// | 15-xx | Grid definition template (See Template 3.N, where N is the grid definition template +// | | number given in octets 13-14) +// | [xx+1]-nn | Optional list of numbers defining number of points (See notes 2, 3, and 4 below) // // If octet 6 is not zero, octets 15-xx (15-nn if octet 11 is zero) may not be supplied. This should be documented with all bits set // to 1 in the grid definition template number. @@ -385,7 +390,7 @@ func (s Section3) String() string { return fmt.Sprint("Point count: ", s.DataPointCount, " Definition: ", GridDefinitionTemplateDescription(int(s.TemplateNumber))) } -//ReadSection3 reads section3 from reader(f). the Lenght parameter is ignored +// ReadSection3 reads section3 from reader(f). the Lenght parameter is ignored func ReadSection3(f io.Reader, _ int) (section Section3, err error) { err = read(f, §ion.Source, §ion.DataPointCount, §ion.PointCountOctets, §ion.PointCountInterpretation, §ion.TemplateNumber) @@ -399,15 +404,16 @@ func ReadSection3(f io.Reader, _ int) (section Section3, err error) { } // Section4 is the Product Definition Section http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_sect4.shtml -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | Length of the section in octets (nn) -// | 5 | Number of the section (4) -// | 6-7 | Number of coordinate values after template (See note 1 below) -// | 8-9 | Product definition template number (See Table 4.0) -// | 10-xx | Product definition template (See product template 4.X, where X is -// | | the number given in octets 8-9) -// | [xx+1]-nn | Optional list of coordinate values (See notes 2 and 3 below) +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | Length of the section in octets (nn) +// | 5 | Number of the section (4) +// | 6-7 | Number of coordinate values after template (See note 1 below) +// | 8-9 | Product definition template number (See Table 4.0) +// | 10-xx | Product definition template (See product template 4.X, where X is +// | | the number given in octets 8-9) +// | [xx+1]-nn | Optional list of coordinate values (See notes 2 and 3 below) // // Coordinate values are intended to document the vertical discretization associated with model data on hybrid coordinate vertical // levels. A value of zero in octets 6-7 indicates that no such values are present. Otherwise the number corresponds to the whole @@ -426,7 +432,7 @@ type Section4 struct { Coordinates []byte `json:"coordinates"` } -//ReadSection4 reads section4 from an io.Reader +// ReadSection4 reads section4 from an io.Reader func ReadSection4(f io.Reader, length int) (section Section4, err error) { err = read(f, §ion.CoordinatesCount, §ion.ProductDefinitionTemplateNumber) if err != nil { @@ -451,14 +457,15 @@ func ReadSection4(f io.Reader, length int) (section Section4, err error) { } // Section5 is Data Representation section http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_sect5.shtml -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | Length of the section in octets (nn) -// | 5 | Number of the section (5) -// | 6-9 | Number of data points where one or more values are specified in Section 7 when a bit map is present, -// | | total number of data points when a bit map is absent. -// | 10-11 | Data representation template number (See Table 5.0 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_table5-0.shtml) -// | 12-nn | Data representation template (See Template 5.X, where X is the number given in octets 10-11) +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | Length of the section in octets (nn) +// | 5 | Number of the section (5) +// | 6-9 | Number of data points where one or more values are specified in Section 7 when a bit map is present, +// | | total number of data points when a bit map is absent. +// | 10-11 | Data representation template number (See Table 5.0 http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_table5-0.shtml) +// | 12-nn | Data representation template (See Template 5.X, where X is the number given in octets 10-11) type Section5 struct { PointsNumber uint32 `json:"pointsNumber"` DataTemplateNumber uint16 `json:"dataTemplateNumber"` @@ -466,7 +473,7 @@ type Section5 struct { Data []byte `json:"dataTemplate"` } -//ReadSection5 is poorly documented other than code +// ReadSection5 is poorly documented other than code func ReadSection5(f io.Reader, length int) (section Section5, err error) { section.Data = make([]byte, length-6) @@ -477,7 +484,7 @@ func ReadSection5(f io.Reader, length int) (section Section5, err error) { } if section.DataTemplateNumber != 0 && section.DataTemplateNumber != 2 && section.DataTemplateNumber != 3 { - return section, fmt.Errorf("Template number not supported: %d", section.DataTemplateNumber) + return section, fmt.Errorf("template number not supported: %d", section.DataTemplateNumber) } return section, nil @@ -486,38 +493,39 @@ func ReadSection5(f io.Reader, length int) (section Section5, err error) { // GetDataTemplate extract DataTemplate from the section func (section Section5) GetDataTemplate() (interface{}, error) { switch section.DataTemplateNumber { - case 0: data := Data0{} - read(bytes.NewReader(section.Data), &data) - return data, nil + err := read(bytes.NewReader(section.Data), &data) + return data, err case 2: data := Data2{} - read(bytes.NewReader(section.Data), &data) - return data, nil + err := read(bytes.NewReader(section.Data), &data) + return data, err case 3: data := Data3{} - read(bytes.NewReader(section.Data), &data) - return data, nil + err := read(bytes.NewReader(section.Data), &data) + return data, err + default: + return struct{}{}, fmt.Errorf("unknown data format") } - - return struct{}{}, fmt.Errorf("Unknown data format") } // Section6 is the Bit-Map section http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_sect6.shtml -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | Length of the section in octets (nn) -// | 5 | Number of the section (6) -// | 6 | Bit-map indicator (See Table 6.0) (See note 1 below) -// | 7-nn | Bit-map +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | Length of the section in octets (nn) +// | 5 | Number of the section (6) +// | 6 | Bit-map indicator (See Table 6.0) (See note 1 below) +// | 7-nn | Bit-map +// // If octet 6 is not zero, the length of this section is 6 and octets 7-nn are not present. type Section6 struct { BitmapIndicator uint8 `json:"bitmapIndicator"` Bitmap []byte `json:"bitmap"` } -//ReadSection6 is poorly documented other than code +// ReadSection6 is poorly documented other than code func ReadSection6(f io.Reader, length int) (section Section6, err error) { section.Bitmap = make([]byte, length-1) @@ -525,17 +533,18 @@ func ReadSection6(f io.Reader, length int) (section Section6, err error) { } // Section7 is the Data section http://www.nco.ncep.noaa.gov/pmb/docs/grib2/grib2_doc/grib2_sect7.shtml -// | Octet Number | Content -// ----------------------------------------------------------------------------------------- -// | 1-4 | Length of the section in octets (nn) -// | 5 | Number of the section (7) -// | 6-nn | Data in a format described by data Template 7.X, where X is the data representation template number -// | | given in octets 10-11 of Section 5. +// +// | Octet Number | Content +// ----------------------------------------------------------------------------------------- +// | 1-4 | Length of the section in octets (nn) +// | 5 | Number of the section (7) +// | 6-nn | Data in a format described by data Template 7.X, where X is the data representation template number +// | | given in octets 10-11 of Section 5. type Section7 struct { Data []float64 `json:"data"` } -//ReadSection7 reads the actual data +// ReadSection7 reads the actual data func ReadSection7(f io.Reader, length int, section5 Section5) (section Section7, sectionError error) { defer func() { if err := recover(); err != nil { @@ -559,7 +568,7 @@ func ReadSection7(f io.Reader, length int, section5 Section5) (section Section7, case Data3: section.Data, sectionError = ParseData3(f, length, &x) default: - sectionError = fmt.Errorf("Unknown data type") + sectionError = fmt.Errorf("unknown data type") return } } @@ -567,7 +576,7 @@ func ReadSection7(f io.Reader, length int, section5 Section5) (section Section7, return section, sectionError } -//read bytes from reader and serialize the bytes into the given data .. pointers +// read bytes from reader and serialize the bytes into the given data .. pointers func read(reader io.Reader, data ...interface{}) (err error) { for _, what := range data { err = binary.Read(reader, binary.BigEndian, what) diff --git a/griblib/specs.go b/griblib/specs.go index b44b474..24bac18 100644 --- a/griblib/specs.go +++ b/griblib/specs.go @@ -4,7 +4,7 @@ import "fmt" // translated from https://github.com/ArtemisiaSolutions/grib2js/blob/master/lib/grib/Grib2Spec.js -//DisciplineDescription DisciplineDescription(Code table 0.0) +// DisciplineDescription DisciplineDescription(Code table 0.0) func DisciplineDescription(value uint8) string { switch value { case 0: @@ -26,7 +26,7 @@ func DisciplineDescription(value uint8) string { } } -//MasterTableDescription MasterTableDescription version number (Code table 1.0) +// MasterTableDescription MasterTableDescription version number (Code table 1.0) func MasterTableDescription(value int) string { switch value { case 0: @@ -56,7 +56,7 @@ func MasterTableDescription(value int) string { } } -//LocalTableVersionNumber LocalTableVersionNumber (Code table 1.1) +// LocalTableVersionNumber LocalTableVersionNumber (Code table 1.1) func LocalTableVersionNumber(value int) string { switch value { case 0: @@ -68,7 +68,7 @@ func LocalTableVersionNumber(value int) string { } } -//ReadReferenceTimeSignificance Significance of reference time (Code table 1.2) +// ReadReferenceTimeSignificance Significance of reference time (Code table 1.2) func ReadReferenceTimeSignificance(value int) string { switch value { case 0: @@ -86,7 +86,7 @@ func ReadReferenceTimeSignificance(value int) string { } } -//ReadProductionStatus Production status of data(Code table 1.3) +// ReadProductionStatus Production status of data(Code table 1.3) func ReadProductionStatus(value int) string { switch value { case 0: @@ -108,7 +108,7 @@ func ReadProductionStatus(value int) string { } } -//ReadDataType Type of data (Code table 1.4) +// ReadDataType Type of data (Code table 1.4) func ReadDataType(value uint8) string { switch value { case 0: @@ -136,7 +136,7 @@ func ReadDataType(value uint8) string { } } -//GridDefinitionSourceDescription GridDefinitionSourceDescription Source of Grid Definition (Code table 3.0) +// GridDefinitionSourceDescription GridDefinitionSourceDescription Source of Grid Definition (Code table 3.0) func GridDefinitionSourceDescription(value int) string { switch value { case 0: @@ -150,7 +150,7 @@ func GridDefinitionSourceDescription(value int) string { } } -//GridDefinitionTemplateDescription GridDefinitionTemplateDescription Grid Definition Template Number (Code table 3.1) +// GridDefinitionTemplateDescription GridDefinitionTemplateDescription Grid Definition Template Number (Code table 3.1) func GridDefinitionTemplateDescription(value int) string { switch value { case 0: @@ -218,7 +218,7 @@ func GridDefinitionTemplateDescription(value int) string { } } -//EarthShapeDescription EarthShapeDescription Shape of the earth (Code table 3.2) +// EarthShapeDescription EarthShapeDescription Shape of the earth (Code table 3.2) func EarthShapeDescription(value int) string { switch value { case 0: @@ -312,7 +312,7 @@ return flags } */ -//SpectralDataRepresentationTypeDescription SpectralDataRepresentationTypeDescription Spectral data representation type (Code table 3.6) +// SpectralDataRepresentationTypeDescription SpectralDataRepresentationTypeDescription Spectral data representation type (Code table 3.6) func SpectralDataRepresentationTypeDescription(value int) string { switch value { case 1: @@ -322,7 +322,7 @@ func SpectralDataRepresentationTypeDescription(value int) string { } } -//ReadSpectralDataRepresentationMode SpectralDataRepresentationModeDescription Spectral data representation mode (Code table 3.7) +// ReadSpectralDataRepresentationMode SpectralDataRepresentationModeDescription Spectral data representation mode (Code table 3.7) func ReadSpectralDataRepresentationMode(value int) string { switch value { case 1: @@ -334,7 +334,7 @@ func ReadSpectralDataRepresentationMode(value int) string { } } -//GridPointPositionDescription Grid point position (code table 3.8) +// GridPointPositionDescription Grid point position (code table 3.8) func GridPointPositionDescription(value int) string { switch value { case 0: @@ -383,7 +383,7 @@ return flags } */ -//ReadListInterpretation Interpretation of list of numbers defining number of points (Code table 3.11) +// ReadListInterpretation Interpretation of list of numbers defining number of points (Code table 3.11) func ReadListInterpretation(value int) string { switch value { case 0: @@ -401,7 +401,7 @@ func ReadListInterpretation(value int) string { } } -//ReadVerticalCoordinatePhysicalMeaning Physical meaning of vertical coordinate (Code table 3.15) +// ReadVerticalCoordinatePhysicalMeaning Physical meaning of vertical coordinate (Code table 3.15) func ReadVerticalCoordinatePhysicalMeaning(value int) string { switch value { case 20: @@ -443,7 +443,7 @@ func ReadVerticalCoordinatePhysicalMeaning(value int) string { } } -//ReadHorizontalLineType Type of horizontal line (Code table 3.20) +// ReadHorizontalLineType Type of horizontal line (Code table 3.20) func ReadHorizontalLineType(value int) string { switch value { case 0: @@ -459,7 +459,7 @@ func ReadHorizontalLineType(value int) string { } } -//ReadVerticalDimensionCoordinateValuesDefinition Vertical dimension coordinate values definition (Code table 3.21) +// ReadVerticalDimensionCoordinateValuesDefinition Vertical dimension coordinate values definition (Code table 3.21) func ReadVerticalDimensionCoordinateValuesDefinition(value int) string { switch value { case 0: @@ -475,7 +475,7 @@ func ReadVerticalDimensionCoordinateValuesDefinition(value int) string { } } -//ReadProductDefinitionTemplateNumber Category Definition Template Number (Code table 4.0) +// ReadProductDefinitionTemplateNumber Category Definition Template Number (Code table 4.0) func ReadProductDefinitionTemplateNumber(value uint16) string { switch value { case 0: @@ -563,7 +563,7 @@ func ReadProductDefinitionTemplateNumber(value uint16) string { } } -//ReadProductDisciplineParameters Discipline of parameters by product discipline (Code table 4.1) +// ReadProductDisciplineParameters Discipline of parameters by product discipline (Code table 4.1) func ReadProductDisciplineParameters(discipline uint8, category uint8) string { switch discipline { //Meteorological Products @@ -721,7 +721,7 @@ func ReadProductDisciplineParameters(discipline uint8, category uint8) string { } } -//ReadProductDisciplineCategoryParameters Parameter number by product discipline and parameter category (code table 4.2) +// ReadProductDisciplineCategoryParameters Parameter number by product discipline and parameter category (code table 4.2) func ReadProductDisciplineCategoryParameters(discipline uint16, category uint8, number uint8) string { switch discipline { //Category Discipline 0: Meteorological products @@ -2935,7 +2935,7 @@ func ReadProductDisciplineCategoryParameters(discipline uint16, category uint8, } } -//ReadGeneratingProcessType Type of generating process (code table 4.3) +// ReadGeneratingProcessType Type of generating process (code table 4.3) func ReadGeneratingProcessType(value int) string { switch value { case 0: @@ -2971,7 +2971,7 @@ func ReadGeneratingProcessType(value int) string { } } -//ReadTimeRangeUnitIndicator Indicator of unit of time range (code table 4.4) +// ReadTimeRangeUnitIndicator Indicator of unit of time range (code table 4.4) func ReadTimeRangeUnitIndicator(value int) string { switch value { case 0: @@ -3005,7 +3005,7 @@ func ReadTimeRangeUnitIndicator(value int) string { } } -//ReadSurfaceTypesUnits Fixed surface types and units (code table 4.5) +// ReadSurfaceTypesUnits Fixed surface types and units (code table 4.5) func ReadSurfaceTypesUnits(value int) string { switch value { case 1: @@ -3173,7 +3173,7 @@ func ReadSurfaceTypesUnits(value int) string { } } -//ReadEnsembleForecastType Type of ensemble forecast (code table 4.6) +// ReadEnsembleForecastType Type of ensemble forecast (code table 4.6) func ReadEnsembleForecastType(value int) string { switch value { case 0: @@ -3195,7 +3195,7 @@ func ReadEnsembleForecastType(value int) string { } } -//ReadDerivedForecast Derived forecast (code table 4.7) +// ReadDerivedForecast Derived forecast (code table 4.7) func ReadDerivedForecast(value int) string { switch value { case 0: @@ -3233,7 +3233,7 @@ func ReadDerivedForecast(value int) string { } } -//ReadClusteringMethod Clustering Method (code table 4.8) +// ReadClusteringMethod Clustering Method (code table 4.8) func ReadClusteringMethod(value int) string { switch value { case 0: @@ -3247,7 +3247,7 @@ func ReadClusteringMethod(value int) string { } } -//ReadProbabilityType Probability Type (code table 4.9) +// ReadProbabilityType Probability Type (code table 4.9) func ReadProbabilityType(value int) string { switch value { case 0: @@ -3267,7 +3267,7 @@ func ReadProbabilityType(value int) string { } } -//ReadStatisticalProcessingType Type of statistical processing (code table 4.10) +// ReadStatisticalProcessingType Type of statistical processing (code table 4.10) func ReadStatisticalProcessingType(value int) string { switch value { case 0: @@ -3331,7 +3331,7 @@ func ReadStatisticalProcessingType(value int) string { } } -//ReadTimeIntervalsType Type of time intervals (code table 4.11) +// ReadTimeIntervalsType Type of time intervals (code table 4.11) func ReadTimeIntervalsType(value int) string { switch value { case 1: @@ -3351,7 +3351,7 @@ func ReadTimeIntervalsType(value int) string { } } -//ReadOperatingMode Operating Mode (code table 4.12) +// ReadOperatingMode Operating Mode (code table 4.12) func ReadOperatingMode(value int) string { switch value { case 0: @@ -3367,7 +3367,7 @@ func ReadOperatingMode(value int) string { } } -//ReadQualityControlIndicator Quality Control Indicator (code table 4.13) +// ReadQualityControlIndicator Quality Control Indicator (code table 4.13) func ReadQualityControlIndicator(value int) string { switch value { case 0: @@ -3381,7 +3381,7 @@ func ReadQualityControlIndicator(value int) string { } } -//ReadClutterFillerIndicator Clutter Filter Indicator (code table 4.14) +// ReadClutterFillerIndicator Clutter Filter Indicator (code table 4.14) func ReadClutterFillerIndicator(value int) string { switch value { case 0: @@ -3395,7 +3395,7 @@ func ReadClutterFillerIndicator(value int) string { } } -//ReadSpatialProcessingType TYPE OF SPATIAL PROCESSING USED TO ARRIVE AT A GIVEN DATA VALUE FROM THE SOURCE DATA (code table 4.15) +// ReadSpatialProcessingType TYPE OF SPATIAL PROCESSING USED TO ARRIVE AT A GIVEN DATA VALUE FROM THE SOURCE DATA (code table 4.15) func ReadSpatialProcessingType(value int) string { switch value { case 0: @@ -3419,7 +3419,7 @@ func ReadSpatialProcessingType(value int) string { } } -//ReadIntervalType Type of interval +// ReadIntervalType Type of interval func ReadIntervalType(value int) string { switch value { case 0: @@ -3453,7 +3453,7 @@ func ReadIntervalType(value int) string { } } -//ReadPrecipitationType Precipitation Type (code table 4.201) +// ReadPrecipitationType Precipitation Type (code table 4.201) func ReadPrecipitationType(value int) string { switch value { case 1: @@ -3473,7 +3473,7 @@ func ReadPrecipitationType(value int) string { } } -//ReadPrecipitableWaterCategory Precipitable water category (code table 4.202) +// ReadPrecipitableWaterCategory Precipitable water category (code table 4.202) func ReadPrecipitableWaterCategory(value int) string { switch value { case 255: @@ -3483,7 +3483,7 @@ func ReadPrecipitableWaterCategory(value int) string { } } -//ReadCloudType Cloud type (code table 4.203) +// ReadCloudType Cloud type (code table 4.203) func ReadCloudType(value int) string { switch value { case 0: @@ -3537,7 +3537,7 @@ func ReadCloudType(value int) string { } } -//ReadThunderstormCoverage Thunderstorm coverage (code table 4.204) +// ReadThunderstormCoverage Thunderstorm coverage (code table 4.204) func ReadThunderstormCoverage(value int) string { switch value { case 0: @@ -3557,7 +3557,7 @@ func ReadThunderstormCoverage(value int) string { } } -//ReadAerosolPresence Aerosol presence (code table 4.205) +// ReadAerosolPresence Aerosol presence (code table 4.205) func ReadAerosolPresence(value int) string { switch value { case 0: @@ -3571,7 +3571,7 @@ func ReadAerosolPresence(value int) string { } } -//ReadVolcanicAsh Volcanic ash (code table 4.206) +// ReadVolcanicAsh Volcanic ash (code table 4.206) func ReadVolcanicAsh(value int) string { switch value { case 0: @@ -3585,7 +3585,7 @@ func ReadVolcanicAsh(value int) string { } } -//ReadIcing Icing (code table 4.207) +// ReadIcing Icing (code table 4.207) func ReadIcing(value int) string { switch value { case 0: @@ -3607,7 +3607,7 @@ func ReadIcing(value int) string { } } -//ReadTurbulence Turbulence (code table 4.208) +// ReadTurbulence Turbulence (code table 4.208) func ReadTurbulence(value int) string { switch value { case 0: @@ -3627,7 +3627,7 @@ func ReadTurbulence(value int) string { } } -//ReadPlanetaryBoundaryLayerRegime Planetary boundary layer regime (code table 4.209) +// ReadPlanetaryBoundaryLayerRegime Planetary boundary layer regime (code table 4.209) func ReadPlanetaryBoundaryLayerRegime(value int) string { switch value { case 1: @@ -3645,7 +3645,7 @@ func ReadPlanetaryBoundaryLayerRegime(value int) string { } } -//ReadContrailIntensity Contrail intensity (code table 4.210) +// ReadContrailIntensity Contrail intensity (code table 4.210) func ReadContrailIntensity(value int) string { switch value { case 0: @@ -3659,7 +3659,7 @@ func ReadContrailIntensity(value int) string { } } -//ReadContrailEngineType Contrail engine type (code table 4.211) +// ReadContrailEngineType Contrail engine type (code table 4.211) func ReadContrailEngineType(value int) string { switch value { case 0: @@ -3675,7 +3675,7 @@ func ReadContrailEngineType(value int) string { } } -//ReadLandUse Land use (code table 4.212) +// ReadLandUse Land use (code table 4.212) func ReadLandUse(value int) string { switch value { case 1: @@ -3711,7 +3711,7 @@ func ReadLandUse(value int) string { } } -//ReadSoilType Soil type (code table 4.213) +// ReadSoilType Soil type (code table 4.213) func ReadSoilType(value int) string { switch value { case 1: @@ -3753,7 +3753,7 @@ func ReadSoilType(value int) string { } } -//ReadRemotelySensedSnowCoverage Remotely Sensed Snow Coverage (code table 4.215) +// ReadRemotelySensedSnowCoverage Remotely Sensed Snow Coverage (code table 4.215) func ReadRemotelySensedSnowCoverage(value int) string { switch value { case 50: @@ -3769,7 +3769,7 @@ func ReadRemotelySensedSnowCoverage(value int) string { } } -//ReadSnowCoveredTerrainElevation Elevation of Snow Covered Terrain (code table 4.216) +// ReadSnowCoveredTerrainElevation Elevation of Snow Covered Terrain (code table 4.216) func ReadSnowCoveredTerrainElevation(value int) string { if value >= 0 && value <= 90 { return "Elevation in increments of 100 m" @@ -3781,7 +3781,7 @@ func ReadSnowCoveredTerrainElevation(value int) string { return fmt.Sprint("Unknown ", value) } -//ReadCloudMaskType Cloud mask type (code table 4.217) +// ReadCloudMaskType Cloud mask type (code table 4.217) func ReadCloudMaskType(value int) string { switch value { case 0: @@ -3799,7 +3799,7 @@ func ReadCloudMaskType(value int) string { } } -//ReadPixelSceneType Pixel scene type (code table 4.218) +// ReadPixelSceneType Pixel scene type (code table 4.218) func ReadPixelSceneType(value int) string { switch value { case 0: @@ -3875,7 +3875,7 @@ func ReadPixelSceneType(value int) string { } } -//ReadCloudTopHeightQuality Cloud top height quality indicator (code table 4.219) +// ReadCloudTopHeightQuality Cloud top height quality indicator (code table 4.219) func ReadCloudTopHeightQuality(value int) string { switch value { case 0: @@ -3893,7 +3893,7 @@ func ReadCloudTopHeightQuality(value int) string { } } -//ReadHorizontalDimensionProcessed Horizontal dimension processed (code table 4.220) +// ReadHorizontalDimensionProcessed Horizontal dimension processed (code table 4.220) func ReadHorizontalDimensionProcessed(value int) string { switch value { case 0: @@ -3907,7 +3907,7 @@ func ReadHorizontalDimensionProcessed(value int) string { } } -//ReadMissingDataTreatment Treatment of missing data (code table 4.221) +// ReadMissingDataTreatment Treatment of missing data (code table 4.221) func ReadMissingDataTreatment(value int) string { switch value { case 0: @@ -3921,7 +3921,7 @@ func ReadMissingDataTreatment(value int) string { } } -//ReadCategoricalResult Categorical Result (code table 4.222) +// ReadCategoricalResult Categorical Result (code table 4.222) func ReadCategoricalResult(value int) string { switch value { case 0: @@ -3941,7 +3941,7 @@ func ReadCategoricalResult(value int) string { } } -//ReadFireDetection Fire Detection Indicator (code table 4.223) +// ReadFireDetection Fire Detection Indicator (code table 4.223) func ReadFireDetection(value int) string { switch value { case 0: @@ -3959,7 +3959,7 @@ func ReadFireDetection(value int) string { } } -//ReadCategoricalOutlook Categorical Outlook (code table 4.224) +// ReadCategoricalOutlook Categorical Outlook (code table 4.224) func ReadCategoricalOutlook(value int) string { switch value { case 0: @@ -3985,7 +3985,7 @@ func ReadCategoricalOutlook(value int) string { } } -//ReadAerosolType Aerosol Type (code table 4.233) +// ReadAerosolType Aerosol Type (code table 4.233) func ReadAerosolType(value int) string { switch value { case 0: @@ -4226,7 +4226,7 @@ func ReadAerosolType(value int) string { // Atmospheric chemical or physical constituent type (code table 4.230) //func ReadAtmosphericChemicalOrPhysicalConstituentType = func ReadAerosolType -//ReadWindGeneratedWaveSpectralDescription Wind-Generated Wave Sectral Description (code table 4.235) +// ReadWindGeneratedWaveSpectralDescription Wind-Generated Wave Sectral Description (code table 4.235) func ReadWindGeneratedWaveSpectralDescription(value int) string { switch value { case 0: @@ -4240,7 +4240,7 @@ func ReadWindGeneratedWaveSpectralDescription(value int) string { } } -//ReadDataRepresentationTemplateNumber Data Representation Template Number (code table 5.0) +// ReadDataRepresentationTemplateNumber Data Representation Template Number (code table 5.0) func ReadDataRepresentationTemplateNumber(value int) string { switch value { case 0: @@ -4270,7 +4270,7 @@ func ReadDataRepresentationTemplateNumber(value int) string { } } -//ReadOriginalFieldValuesType Type of original field values (code table 5.1) +// ReadOriginalFieldValuesType Type of original field values (code table 5.1) func ReadOriginalFieldValuesType(value int) string { switch value { case 0: @@ -4284,7 +4284,7 @@ func ReadOriginalFieldValuesType(value int) string { } } -//ReadMatrixCoordinateValueFunctionDefinition Matrix coordinate value function definition (code table 5.2) +// ReadMatrixCoordinateValueFunctionDefinition Matrix coordinate value function definition (code table 5.2) func ReadMatrixCoordinateValueFunctionDefinition(value int) string { switch value { case 0: @@ -4300,7 +4300,7 @@ func ReadMatrixCoordinateValueFunctionDefinition(value int) string { } } -//ReadMatrixCoordinateParameter Matrix coordinate parameter (code table 5.3) +// ReadMatrixCoordinateParameter Matrix coordinate parameter (code table 5.3) func ReadMatrixCoordinateParameter(value int) string { switch value { case 1: @@ -4316,7 +4316,7 @@ func ReadMatrixCoordinateParameter(value int) string { } } -//ReadGroupSplittingMethod ReadGroupSplittingMethod - Group Splitting Method (code table 5.4) +// ReadGroupSplittingMethod ReadGroupSplittingMethod - Group Splitting Method (code table 5.4) func ReadGroupSplittingMethod(value int) string { switch value { case 0: @@ -4330,7 +4330,7 @@ func ReadGroupSplittingMethod(value int) string { } } -//ReadMissingValueManagement ReadMissingValueManagement - Missing Value Management for Complex Packing (code table 5.5) +// ReadMissingValueManagement ReadMissingValueManagement - Missing Value Management for Complex Packing (code table 5.5) func ReadMissingValueManagement(value int) string { switch value { case 0: @@ -4346,7 +4346,7 @@ func ReadMissingValueManagement(value int) string { } } -//ReadSpatialDifferencingOrder ReadSpatialDifferencingOrder Order of Spatial Differencing (code table 5.6) +// ReadSpatialDifferencingOrder ReadSpatialDifferencingOrder Order of Spatial Differencing (code table 5.6) func ReadSpatialDifferencingOrder(value int) string { switch value { case 1: @@ -4360,7 +4360,7 @@ func ReadSpatialDifferencingOrder(value int) string { } } -//ReadFloatingPointNumbersPrecision ReadFloatingPointNumbersPrecision maps Precision of floating-point numbers to a string (code table 5.7) +// ReadFloatingPointNumbersPrecision ReadFloatingPointNumbersPrecision maps Precision of floating-point numbers to a string (code table 5.7) func ReadFloatingPointNumbersPrecision(value int) string { switch value { case 1: @@ -4376,7 +4376,7 @@ func ReadFloatingPointNumbersPrecision(value int) string { } } -//ReadCompressionType ReadCompressionType maps Type of compression (code table 5.40) +// ReadCompressionType ReadCompressionType maps Type of compression (code table 5.40) func ReadCompressionType(value int) string { switch value { case 0: @@ -4390,7 +4390,7 @@ func ReadCompressionType(value int) string { } } -//ReadBitMapIndicator ReadBitMapIndicator is a Bit Map Indicator (code table 6.0) +// ReadBitMapIndicator ReadBitMapIndicator is a Bit Map Indicator (code table 6.0) func ReadBitMapIndicator(value int) string { if value == 0 { return "A bit map applies to this product and is specified in this Section" diff --git a/internal/reader/bitreader.go b/internal/reader/bitreader.go index 31b020b..d8052fc 100644 --- a/internal/reader/bitreader.go +++ b/internal/reader/bitreader.go @@ -88,10 +88,6 @@ func newReader(r io.ByteReader) *BitReader { return &BitReader{r, 0, 0} } -func (r *BitReader) currentBit() byte { - return (r.byte >> (7 - r.offset)) & 0x01 -} - func (r *BitReader) readBit() (uint, error) { if r.offset == 8 || r.offset == 0 { r.offset = 0 diff --git a/main.go b/main.go index ddb70d2..fcc3bd8 100644 --- a/main.go +++ b/main.go @@ -65,7 +65,12 @@ func main() { log.Printf("\nFile [%s] not found.\n", options.Filepath) os.Exit(1) } - defer gribFile.Close() + defer func(gribFile *os.File) { + err2 := gribFile.Close() + if err2 != nil { + log.Printf("Error closing gribFile: %s", err2.Error()) + } + }(gribFile) switch options.Operation { case "parse": @@ -91,7 +96,12 @@ func reduceToFile(gribFile io.Reader, options griblib.Options) { os.Exit(1) } - defer reduceFile.Close() + defer func(reduceFile *os.File) { + err2 := reduceFile.Close() + if err2 != nil { + log.Printf("Error closing reduceFile: %s", err2.Error()) + } + }(reduceFile) end := make(chan bool) content := make(chan []byte) @@ -104,7 +114,13 @@ func reduceToFile(gribFile io.Reader, options griblib.Options) { log.Printf("reduce done to file '%s'. \n", options.ReduceFilePath) return case bytesRead := <-content: - reduceFile.Write(bytesRead) + written, err2 := reduceFile.Write(bytesRead) + if written != len(bytesRead) { + log.Printf("written: %d, len: %d", written, len(bytesRead)) + } + if err2 != nil { + log.Printf("Error writing to reduceFile: %s", err2.Error()) + } } } From 41f896307e7737f18881e696480d53867733d1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20GIRAUD?= Date: Fri, 21 Jun 2024 16:56:00 +0200 Subject: [PATCH 2/2] more lint --- griblib/data2.go | 2 +- griblib/exports.go | 4 ++-- griblib/filters.go | 5 +++-- griblib/gribtest/data3_test.go | 14 +++++++------- griblib/gribtest/pngExport_test.go | 10 +++++----- griblib/gribtest/sections_test.go | 23 ++++++++++++++++------- griblib/pngExport.go | 10 +++++----- griblib/reducer.go | 4 ++-- main.go | 10 +++++----- 9 files changed, 46 insertions(+), 36 deletions(-) diff --git a/griblib/data2.go b/griblib/data2.go index 5d901c6..d7199bb 100644 --- a/griblib/data2.go +++ b/griblib/data2.go @@ -203,7 +203,7 @@ func ParseData2(dataReader io.Reader, dataLength int, template *Data2) ([]float6 // section7Data, ifldmiss, err := template.extractData(bitReader, bitGroups) if err != nil { - return nil, fmt.Errorf("Data extract: %s", err.Error()) + return nil, fmt.Errorf("data extract: %s", err.Error()) } return template.scaleValues(section7Data, ifldmiss), nil diff --git a/griblib/exports.go b/griblib/exports.go index a445071..930cb86 100644 --- a/griblib/exports.go +++ b/griblib/exports.go @@ -33,7 +33,7 @@ func Export(messages []*Message, options Options) { case ExportToPNG: ExportMessagesAsPngs(messages) default: - log.Printf("Error: Export type %d not supported. \n", options.ExportType) + log.Fatalf("Error: Export type %d not supported. \n", options.ExportType) } } @@ -67,7 +67,7 @@ func export(m *Message) { var out bytes.Buffer err := json.Compact(&out, js) if err != nil { - log.Printf("Error compacting json: %v\n", err) + log.Fatalf("Error compacting json: %v\n", err) } _, _ = out.WriteTo(os.Stdout) log.Println("") diff --git a/griblib/filters.go b/griblib/filters.go index bedbd70..ed2425a 100644 --- a/griblib/filters.go +++ b/griblib/filters.go @@ -38,7 +38,9 @@ const ( func Filter(messages []*Message, options Options) []*Message { filtered := make([]*Message, 0) - + if !isEmpty(options.GeoFilter) && len(messages) > 0 { + log.Printf("Using GeoFilter %v\n", options.GeoFilter) + } for _, message := range messages { discipline := satisfiesDiscipline(options.Discipline, message) category := satisfiesCategory(options.Category, message) @@ -47,7 +49,6 @@ func Filter(messages []*Message, options Options) []*Message { continue } if !isEmpty(options.GeoFilter) { - log.Printf("Using GeoFilter %v\n", options.GeoFilter) if data, err := FilterValuesFromGeoFilter(message, options.GeoFilter); err == nil { message.Section7.Data = *data if grid0, ok := message.Section3.Definition.(*Grid0); ok { diff --git a/griblib/gribtest/data3_test.go b/griblib/gribtest/data3_test.go index 6a9b3cb..6cc7bc8 100644 --- a/griblib/gribtest/data3_test.go +++ b/griblib/gribtest/data3_test.go @@ -23,22 +23,22 @@ func Test_read_integrationtest_file(t *testing.T) { if surface.Type == 1 && // ground surface m.Section0.Discipline == 0 && // meterology m.Section4.ProductDefinitionTemplate.ParameterCategory == 0 { // temperature - var max float64 = 00 - var min float64 = 1000 + var maxTemp float64 = 00 + var minTemp float64 = 1000 for _, kelvin := range m.Section7.Data { if kelvin < 197 || kelvin > 350 { t.Errorf("Got kelvin out of range: %f\n", kelvin) } - if kelvin > max { - max = kelvin + if kelvin > maxTemp { + maxTemp = kelvin } - if kelvin < min { - min = kelvin + if kelvin < minTemp { + minTemp = kelvin } } log.Printf("category number %v,", m.Section4.ProductDefinitionTemplate.ParameterCategory) log.Printf("parameter number %v,", m.Section4.ProductDefinitionTemplate.ParameterNumber) - log.Printf("surface type %v, surface value %v max: %f min: %f\n", surface.Type, surface.Value, max, min) + log.Printf("surface type %v, surface value %v maxTemp: %f minTemp: %f\n", surface.Type, surface.Value, maxTemp, minTemp) } } diff --git a/griblib/gribtest/pngExport_test.go b/griblib/gribtest/pngExport_test.go index b1fcc54..24e9e21 100644 --- a/griblib/gribtest/pngExport_test.go +++ b/griblib/gribtest/pngExport_test.go @@ -57,12 +57,12 @@ func Test_message_to_png(t *testing.T) { } func Test_maxmin(t *testing.T) { - max, min := griblib.MaxMin([]float64{0, -154, 54, 64, -10}) - if max != 64.0 { - t.Errorf("Expected max to be 64, was %f", max) + biggest, smallest := griblib.MaxMin([]float64{0, -154, 54, 64, -10}) + if biggest != 64.0 { + t.Errorf("Expected biggest to be 64, was %f", biggest) } - if min != -154.0 { - t.Errorf("Expected min to be -154, was %f", min) + if smallest != -154.0 { + t.Errorf("Expected smallest to be -154, was %f", smallest) } } diff --git a/griblib/gribtest/sections_test.go b/griblib/gribtest/sections_test.go index 4b79cad..bfcb8b9 100644 --- a/griblib/gribtest/sections_test.go +++ b/griblib/gribtest/sections_test.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/binary" "io" - "log" "testing" "github.com/nilsmagnus/grib/griblib" @@ -20,7 +19,12 @@ func Test_read_section0(t *testing.T) { Reserved: 6, } - section0, readError := griblib.ReadSection0(toIoReader(testData)) + ioReader, err := toIoReader(testData) + if err != nil { + t.Fatal(err) + } + + section0, readError := griblib.ReadSection0(ioReader) if readError != nil { t.Fatal(readError) @@ -50,7 +54,12 @@ func Test_read_section1(t *testing.T) { Type: 8, } - section1, readError := griblib.ReadSection1(toIoReader(testData), binary.Size(testData)) + ioReader, err := toIoReader(testData) + if err != nil { + t.Fatal(err) + } + + section1, readError := griblib.ReadSection1(ioReader, binary.Size(testData)) if readError != nil { t.Fatal(readError) @@ -58,20 +67,20 @@ func Test_read_section1(t *testing.T) { if testData != section1 { t.Error("Deserialized section1 struct is not equal to original struct") + t.Fail() } } // create a reader from a struct for testing purposes -func toIoReader(data interface{}) (reader io.Reader) { +func toIoReader(data interface{}) (reader io.Reader, err error) { var binBuf bytes.Buffer - err := binary.Write(&binBuf, binary.BigEndian, data) + err = binary.Write(&binBuf, binary.BigEndian, data) if err != nil { - log.Printf("Error writing to buffer: %s", err.Error()) + return } reader = bytes.NewReader(binBuf.Bytes()) return - } diff --git a/griblib/pngExport.go b/griblib/pngExport.go index 9a6ce67..732d341 100644 --- a/griblib/pngExport.go +++ b/griblib/pngExport.go @@ -16,11 +16,11 @@ func ExportMessagesAsPngs(messages []*Message) { for i, message := range messages { dataImage, err := imageFromMessage(message) if err != nil { - log.Printf("Message could not be converted to image: %v\n", err) + log.Fatalf("Message could not be converted to image: %v\n", err) } else { err2 := writeImageToFilename(dataImage, imageFileName(i, message)) if err2 != nil { - log.Printf("Image could not be written to file: %v\n", err2) + log.Fatalf("Image could not be written to file: %v\n", err2) } } } @@ -52,13 +52,13 @@ func writeImageToFilename(img image.Image, name string) error { if err2 := png.Encode(f, img); err2 != nil { err3 := f.Close() if err3 != nil { - log.Printf("Error closing file: %v\n", err3) + log.Fatalf("Error closing file: %v\n", err3) } return err2 } - if err := f.Close(); err != nil { - return err + if err2 := f.Close(); err2 != nil { + return err2 } return nil } diff --git a/griblib/reducer.go b/griblib/reducer.go index aae80b3..5a0a2ff 100644 --- a/griblib/reducer.go +++ b/griblib/reducer.go @@ -45,10 +45,10 @@ func Reduce(readSeeker io.Reader, options Options, content chan []byte, end chan length := int64(section0.MessageLength) - 16 bytesRead, err2 := readSeeker.Read(make([]byte, length)) if int64(bytesRead) != length { - log.Printf("bytesRead: %v, length: %v", bytesRead, length) + log.Fatalf("bytesRead: %v, length: %v", bytesRead, length) } if err2 != nil { - log.Printf("read3 err: %v", err2.Error()) + log.Fatalf("read3 err: %v", err2.Error()) } } diff --git a/main.go b/main.go index fcc3bd8..adf85d6 100644 --- a/main.go +++ b/main.go @@ -68,7 +68,7 @@ func main() { defer func(gribFile *os.File) { err2 := gribFile.Close() if err2 != nil { - log.Printf("Error closing gribFile: %s", err2.Error()) + log.Fatalf("Error closing gribFile: %s\n", err2.Error()) } }(gribFile) @@ -78,7 +78,7 @@ func main() { case "reduce": reduceToFile(gribFile, options) default: - log.Printf("Operation '%s' not supported. Valid values are 'parse' and 'reduce'.", options.Operation) + log.Printf("Operation '%s' not supported. Valid values are 'parse' and 'reduce'.\n", options.Operation) os.Exit(1) } } @@ -99,7 +99,7 @@ func reduceToFile(gribFile io.Reader, options griblib.Options) { defer func(reduceFile *os.File) { err2 := reduceFile.Close() if err2 != nil { - log.Printf("Error closing reduceFile: %s", err2.Error()) + log.Fatalf("Error closing reduceFile: %s", err2.Error()) } }(reduceFile) @@ -116,10 +116,10 @@ func reduceToFile(gribFile io.Reader, options griblib.Options) { case bytesRead := <-content: written, err2 := reduceFile.Write(bytesRead) if written != len(bytesRead) { - log.Printf("written: %d, len: %d", written, len(bytesRead)) + log.Fatalf("written: %d, len: %d", written, len(bytesRead)) } if err2 != nil { - log.Printf("Error writing to reduceFile: %s", err2.Error()) + log.Fatalf("Error writing to reduceFile: %s", err2.Error()) } } }