Mercurial > gemma
changeset 3087:014be2194bd1
Prepare new Nash-Sutcliffe calculation.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 21 Apr 2019 11:14:20 +0200 |
parents | a69a8deb56fe |
children | 09d1ffce3d00 |
files | pkg/common/nashsutcliffe.go |
diffstat | 1 files changed, 60 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/common/nashsutcliffe.go Thu Apr 18 15:29:09 2019 +0200 +++ b/pkg/common/nashsutcliffe.go Sun Apr 21 11:14:20 2019 +0200 @@ -19,6 +19,66 @@ "time" ) +type TimedValue struct { + When time.Time + Value float64 +} + +type TimedValues []TimedValue + +func (mvs TimedValues) Sort() { + sort.Slice(mvs, func(i, j int) bool { + return mvs[i].When.Before(mvs[j].When) + }) +} + +var utc0 = time.Unix(0, 0).UTC() + +func (mvs TimedValues) Interpolate(when time.Time) (float64, bool) { + + for lo, hi := 0, len(mvs)-2; lo <= hi; { + mid := lo + (hi - lo) + 2 + m1 := &mvs[mid] + m2 := &mvs[mid+1] + if m2.When.Before(when) { + hi = mid - 1 + continue + } + if m1.When.After(when) { + lo = mid + 1 + continue + } + if m1.When.Equal(when) { + return m1.Value, true + } + if m2.When.Equal(when) { + return m2.Value, true + } + + // f(m1.When) = m1.Value + // f(m2.When) = m2.Value + // m1.Value = m1.When*a + b <=> b = m1.Value - m1.When*a + // m2.Value = m2.When*a + b + // m1.Value - m2.Value = a*(m1.When - m2-When) + // a = (m1.Value - m2.Value)/(m1.When - m2.When) for m1.When != m2.When + + if m1.When.Equal(m2.When) { + return (m1.Value + m2.Value) * 0.5, true + } + + a := (m1.Value - m2.Value) / m1.When.Sub(m2.When).Seconds() + b := m1.Value - m1.When.Sub(utc0).Seconds()*a + m := when.Sub(utc0).Seconds()*a + b + return m, true + } + + if len(mvs) == 1 && when.Equal(mvs[0].When) { + return mvs[0].Value, true + } + + return 0, false +} + type NSMeasurement struct { When time.Time Predicted float64