go-hep.org/x/hep@v0.38.1/hplot/ticks.go (about) 1 // Copyright ©2016 The go-hep Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package hplot 6 7 import ( 8 "fmt" 9 "math" 10 "strconv" 11 12 "go-hep.org/x/hep/hplot/internal/talbot" 13 "gonum.org/v1/gonum/floats/scalar" 14 "gonum.org/v1/plot" 15 ) 16 17 const ( 18 // displayPrecision is a sane level of float precision for a plot. 19 displayPrecision = 4 20 ) 21 22 // FreqTicks implements a simple plot.Ticker scheme. 23 // FreqTicks will generate N ticks where 1 every Freq tick will be labeled. 24 type FreqTicks struct { 25 N int // number of ticks 26 Freq int // frequency of labeled ticks 27 } 28 29 // Ticks returns Ticks in a specified range 30 func (ft FreqTicks) Ticks(min, max float64) []plot.Tick { 31 prec := maxInt(precisionOf(min), precisionOf(max)) 32 ticks := make([]plot.Tick, ft.N) 33 for i := range ticks { 34 v := min + float64(i)*(max-min)/float64(len(ticks)-1) 35 label := "" 36 if i%ft.Freq == 0 { 37 label = formatFloatTick(v, prec) 38 } 39 ticks[i] = plot.Tick{Value: v, Label: label} 40 } 41 return ticks 42 } 43 44 // formatFloatTick returns a g-formated string representation of v 45 // to the specified precision. 46 func formatFloatTick(v float64, prec int) string { 47 return strconv.FormatFloat(scalar.Round(v, prec), 'g', displayPrecision, 64) 48 } 49 50 // precisionOf returns the precision needed to display x without e notation. 51 func precisionOf(x float64) int { 52 return int(math.Max(math.Ceil(-math.Log10(math.Abs(x))), displayPrecision)) 53 } 54 55 func maxInt(a, b int) int { 56 if a > b { 57 return a 58 } 59 return b 60 } 61 62 // NoTicks implements plot.Ticker but does not display any tick. 63 type NoTicks struct{} 64 65 // Ticks returns Ticks in a specified range 66 func (NoTicks) Ticks(min, max float64) []plot.Tick { 67 return nil 68 } 69 70 // Ticks implements plot.Ticker. 71 // Ticks allows to specify the maximum number of major ticks to display. 72 // The zero value of Ticks display a maximum number of 3 major ticks. 73 type Ticks struct { 74 N int // N is the suggested number of major ticks to display. 75 76 // Format is an optional major-tick formatter. 77 // If empty, a format will be automatically chosen. 78 Format string 79 } 80 81 func (tck Ticks) Ticks(min, max float64) []plot.Tick { 82 if tck.N == 0 { 83 tck.N = 3 // same default than plot.DefaultTicks 84 } 85 86 ticks := talbot.Ticks(min, max, tck.N) 87 if xfmt := tck.Format; xfmt != "" { 88 for i, tck := range ticks { 89 if tck.IsMinor() { 90 continue 91 } 92 ticks[i].Label = fmt.Sprintf(xfmt, tck.Value) 93 } 94 } 95 return ticks 96 }