Added control to prevent invalid low/high ranges

This commit is contained in:
Daniel Gil 2018-05-29 17:51:41 +02:00
parent 6702d50231
commit 90c4e64922
6 changed files with 64 additions and 23 deletions

View File

@ -30,6 +30,11 @@ const (
PlotTypeMerged PlotTypeMerged
) )
type Superplot struct {
Plot *plot.Plot
NumElements int
}
var ( var (
openBracket = "[" openBracket = "["
closeBracket = "]" closeBracket = "]"
@ -119,7 +124,7 @@ func convertToPlotterXYs(intervals []*interval.Interval) plotter.XYs {
return pxys return pxys
} }
func alignPlots(plotItems []*plot.Plot) *vgimg.Canvas { func alignPlots(plotItems []*Superplot) *vgimg.Canvas {
rows, cols := len(plotItems), 1 rows, cols := len(plotItems), 1
plots := make([][]*plot.Plot, rows) plots := make([][]*plot.Plot, rows)
for j := 0; j < rows; j++ { for j := 0; j < rows; j++ {
@ -128,10 +133,10 @@ func alignPlots(plotItems []*plot.Plot) *vgimg.Canvas {
p := plotItems[j] p := plotItems[j]
// make sure the horizontal scales match // make sure the horizontal scales match
p.X.Min = MinX p.Plot.X.Min = MinX
p.X.Max = MaxX p.Plot.X.Max = MaxX
plots[j][i] = p plots[j][i] = p.Plot
} }
} }
@ -171,7 +176,7 @@ func createFileFromCanvas(path string, img *vgimg.Canvas) error {
return nil return nil
} }
func createPlot(title string, xys plotter.XYs, plotType PlotType) (*plot.Plot, error) { func createPlot(title string, xys plotter.XYs, plotType PlotType) (*Superplot, error) {
p, err := plot.New() p, err := plot.New()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not create plot: %v", err) return nil, fmt.Errorf("could not create plot: %v", err)
@ -181,15 +186,15 @@ func createPlot(title string, xys plotter.XYs, plotType PlotType) (*plot.Plot, e
p.Add(plotter.NewGrid()) p.Add(plotter.NewGrid())
p.Title.Text = title p.Title.Text = title
p.HideY() p.HideY()
// p.X.Label.Text = "values"
p.X.Padding = vg.Length(5) p.X.Padding = vg.Length(5)
p.Y.Padding = vg.Length(20) p.Y.Padding = vg.Length(20)
plotIntervals(p, plotType, xys) plotIntervals(p, plotType, xys)
return p, nil return &Superplot{p, xys.Len()}, nil
} }
func plotData(path string, intervals interval.Intervals) error { func plotData(path string, intervals interval.Intervals) error {
plots := []*plot.Plot{} plots := []*Superplot{}
// create Intervals plot // create Intervals plot
xysIntervals := convertToPlotterXYs(intervals.Get()) xysIntervals := convertToPlotterXYs(intervals.Get())

View File

@ -1,5 +1,7 @@
package interval package interval
import "fmt"
func (intvls *intervals) FindIntervalsForValue(value int) []*Interval { func (intvls *intervals) FindIntervalsForValue(value int) []*Interval {
// sort intervals (if necessary) // sort intervals (if necessary)
intvls.Sort() intvls.Sort()
@ -7,7 +9,11 @@ func (intvls *intervals) FindIntervalsForValue(value int) []*Interval {
var matches []*Interval var matches []*Interval
for _, intvl := range intvls.Intervals { for _, intvl := range intvls.Intervals {
// convert if necessary exclusive low/high values into inclusive ones // convert if necessary exclusive low/high values into inclusive ones
low, high := intvls.getInclusives(intvl.Low, intvl.High) low, high, err := intvls.getInclusives(intvl.Low, intvl.High)
if err != nil {
fmt.Printf("FindIntervalsForValue - unable to get inclusives: %v", err)
continue
}
// check if we have to stop searching // check if we have to stop searching
if low > value { if low > value {

View File

@ -1,5 +1,7 @@
package interval package interval
import "fmt"
func (intvls *intervals) HasGaps() bool { func (intvls *intervals) HasGaps() bool {
intvls.Gaps() intvls.Gaps()
if intvls.GapsList != nil && len(intvls.GapsList) > 0 { if intvls.GapsList != nil && len(intvls.GapsList) > 0 {
@ -27,7 +29,11 @@ func (intvls *intervals) calculateGaps() []*Interval {
gapThreshold := intvls.MinLow gapThreshold := intvls.MinLow
for _, intvl := range intvls.Intervals { for _, intvl := range intvls.Intervals {
// convert if necessary exclusive low/high values into inclusive ones // convert if necessary exclusive low/high values into inclusive ones
low, high := intvls.getInclusives(intvl.Low, intvl.High) low, high, err := intvls.getInclusives(intvl.Low, intvl.High)
if err != nil {
fmt.Printf("calculateGaps - unable to get inclusives: %v", err)
continue
}
// if the current Low is higher than the last maximal High, means that there is a gap so we add this gap to the list // if the current Low is higher than the last maximal High, means that there is a gap so we add this gap to the list
if low > gapThreshold { if low > gapThreshold {

View File

@ -1,15 +1,22 @@
package interval package interval
func (intvls *intervals) getInclusives(intervalLow, intervalHigh int) (int, int) { import (
"fmt"
)
func (intvls *intervals) getInclusives(intervalLow, intervalHigh int) (int, int, error) {
low := intvls.getInclusiveLow(intervalLow) low := intvls.getInclusiveLow(intervalLow)
high := intvls.getInclusiveHigh(intervalHigh) high := intvls.getInclusiveHigh(intervalHigh)
if high < low {
high = low // if we get an incoherent result it's because it's invalid, for example in this case:
} // (low,high)=(0,1) --> if we add 1 to the Low and substract 1 to the High ends with (1,0) which is not valid
if low > high { if low > high {
low = high return 0, 0, fmt.Errorf("low (%v) can not be bigger than high (%v)", low, high)
} }
return low, high if high < low {
return 0, 0, fmt.Errorf("high (%v) can not be smaller than low (%v)", high, low)
}
return low, high, nil
} }
func (intvls *intervals) getInclusiveLow(value int) int { func (intvls *intervals) getInclusiveLow(value int) int {

View File

@ -1,5 +1,7 @@
package interval package interval
import "github.com/labstack/gommon/log"
func (intvls *intervals) Merge() []*Interval { func (intvls *intervals) Merge() []*Interval {
if intvls.MergeList == nil { if intvls.MergeList == nil {
intvls.MergeList = intvls.calculateMerged() intvls.MergeList = intvls.calculateMerged()
@ -18,14 +20,20 @@ func (intvls *intervals) calculateMerged() []*Interval {
var currentMinLow int var currentMinLow int
var currentMaxHigh int var currentMaxHigh int
for i, intvl := range intvls.Intervals { firstInitDone := false
for _, intvl := range intvls.Intervals {
// convert if necessary exclusive low/high values into inclusive ones // convert if necessary exclusive low/high values into inclusive ones
low, high := intvls.getInclusives(intvl.Low, intvl.High) low, high, err := intvls.getInclusives(intvl.Low, intvl.High)
if err != nil {
log.Errorf("calculateMerged - unable to get inclusives: %v", err)
continue
}
// in the first iteration it's for sure that don't exists merge, we just initialize variables // in the first iteration it's for sure that don't exists merge, we just initialize variables
if i == 0 { if !firstInitDone {
currentMinLow = low currentMinLow = low
currentMaxHigh = high currentMaxHigh = high
firstInitDone = true
continue continue
} }

View File

@ -1,6 +1,9 @@
package interval package interval
import "math" import (
"fmt"
"math"
)
func (intvls *intervals) HasOverlapped() bool { func (intvls *intervals) HasOverlapped() bool {
intvls.Overlapped() intvls.Overlapped()
@ -28,12 +31,17 @@ func (intvls *intervals) calculateOverlapped() []*Interval {
lastMinLow := math.MaxInt64 lastMinLow := math.MaxInt64
lastMaxHigh := math.MinInt64 lastMaxHigh := math.MinInt64
for i, intvl := range intvls.Intervals { firstInitDone := false
for _, intvl := range intvls.Intervals {
// convert if necessary exclusive low/high values into inclusive ones // convert if necessary exclusive low/high values into inclusive ones
low, high := intvls.getInclusives(intvl.Low, intvl.High) low, high, err := intvls.getInclusives(intvl.Low, intvl.High)
if err != nil {
fmt.Printf("calculateOverlapped - unable to get inclusives: %v", err)
continue
}
// for the first iteration make no sense those operations // for the first iteration make no sense those operations
if i > 0 { if firstInitDone {
// check if the front or back side of the current segment overlaps with the previous one // check if the front or back side of the current segment overlaps with the previous one
lowInBetween := isLowInBetweenInclusive(lastMinLow, lastMaxHigh, low, high) lowInBetween := isLowInBetweenInclusive(lastMinLow, lastMaxHigh, low, high)
highInBetween := isHighInBetweenInclusive(lastMinLow, lastMaxHigh, low, high) highInBetween := isHighInBetweenInclusive(lastMinLow, lastMaxHigh, low, high)
@ -51,6 +59,7 @@ func (intvls *intervals) calculateOverlapped() []*Interval {
if high > lastMaxHigh { if high > lastMaxHigh {
lastMaxHigh = high lastMaxHigh = high
} }
firstInitDone = true
} }
return list return list
} }