comparison pkg/common/nashsutcliffe.go @ 3099:f516ac26f4db direct-match-nash-sutcliffe

"Sharp" match for predicted and measured values in nash sutcliffe.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 24 Apr 2019 22:26:16 +0200
parents 8f2ac24b0cb3
children 247e78ba2bf7
comparison
equal deleted inserted replaced
3098:8f2ac24b0cb3 3099:f516ac26f4db
30 sort.Slice(mvs, func(i, j int) bool { 30 sort.Slice(mvs, func(i, j int) bool {
31 return mvs[i].When.Before(mvs[j].When) 31 return mvs[i].When.Before(mvs[j].When)
32 }) 32 })
33 } 33 }
34 34
35 var utc0 = time.Unix(0, 0).UTC() 35 func epsEquals(a, b time.Time) bool {
36 d := a.Sub(b)
37 return -10*time.Millisecond < d && d < 10*time.Millisecond
38 }
36 39
37 func (mvs TimedValues) Interpolate(when time.Time) (float64, bool) { 40 func (mvs TimedValues) Find(when time.Time) (float64, bool) {
38 41 for i := range mvs {
39 for lo, hi := 0, len(mvs)-2; lo <= hi; { 42 if epsEquals(when, mvs[i].When) {
40 mid := lo + (hi-lo)/2 43 return mvs[i].Value, true
41 m1 := &mvs[mid]
42 m2 := &mvs[mid+1]
43 if m2.When.Before(when) {
44 hi = mid - 1
45 continue
46 }
47 if m1.When.After(when) {
48 lo = mid + 1
49 continue
50 }
51 if m1.When.Equal(when) {
52 //log.Printf("matches first: %f\n", m1.Value)
53 return m1.Value, true
54 }
55 if m2.When.Equal(when) {
56 //log.Printf("matches second: %f\n", m1.Value)
57 return m2.Value, true
58 }
59
60 // f(m1.When) = m1.Value
61 // f(m2.When) = m2.Value
62 // m1.Value = m1.When*a + b <=> b = m1.Value - m1.When*a
63 // m2.Value = m2.When*a + b
64 // m1.Value - m2.Value = a*(m1.When - m2-When)
65 // a = (m1.Value - m2.Value)/(m1.When - m2.When) for m1.When != m2.When
66
67 if m1.When.Equal(m2.When) {
68 return (m1.Value + m2.Value) * 0.5, true
69 }
70
71 a := (m1.Value - m2.Value) / m1.When.Sub(m2.When).Seconds()
72 b := m1.Value - m1.When.Sub(utc0).Seconds()*a
73 m := when.Sub(utc0).Seconds()*a + b
74
75 //log.Printf("%f %f %f\n", m1.Value, m, m2.Value)
76 return m, true
77 }
78
79 if l := len(mvs); l > 0 {
80 if when.Equal(mvs[0].When) {
81 //log.Printf("at start\n")
82 return mvs[0].Value, true
83 }
84 if !when.Before(mvs[l-1].When) {
85 //log.Printf("after end\n")
86 return mvs[l-1].Value, true
87 } 44 }
88 } 45 }
89
90 //if len(mvs) > 0 {
91 // log.Printf("does not match %v %v %v\n",
92 // mvs[0].When, mvs[len(mvs)-1].When.Sub(mvs[0].When), when)
93 //}
94
95 return 0, false 46 return 0, false
96 } 47 }
97 48
98 func NashSutcliffe(predicted, observed []float64) float64 { 49 func NashSutcliffe(predicted, observed []float64) float64 {
99 50