Mercurial > gemma
view pkg/common/nashsutcliffe.go @ 2741:87aed4f9b1b8
Added calculation of Nash Sutcliffe efficiency coefficents.
GET /api/data/nash-sutcliffe/{gauge}?when={WHEN}
'when' is optional in form of "2006-01-02T15:04:05.000" and defaults to
current server time.
curl -H "X-Gemma-Auth:$KEY" http://${server}:${port}/api/data/nash-sutcliffe/${gauge} | jq .
{
"when": "2019-03-20T10:38:05.687",
"coeffs": [
{
"value": 0,
"samples": 0,
"hours": 24
},
{
"value": 0,
"samples": 0,
"hours": 48
},
{
"value": 0,
"samples": 0,
"hours": 72
}
]
}
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 20 Mar 2019 10:47:01 +0100 |
parents | |
children | 4f66a3ba424b |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2019 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> package common import ( "sort" "time" ) type NSMeasurement struct { When time.Time Predicted float64 Observed float64 } func NashSutcliffeSort(measurements []NSMeasurement) { sort.Slice(measurements, func(i, j int) bool { return measurements[i].When.Before(measurements[j].When) }) } func NashSutcliffe(measurements []NSMeasurement, from, to time.Time) (float64, int) { if len(measurements) == 0 { return 0, 0 } if to.Before(from) { from, to = to, from } begin := sort.Search(len(measurements), func(i int) bool { return !measurements[i].When.Before(from) }) if begin >= len(measurements) { return 0, 0 } end := sort.Search(len(measurements), func(i int) bool { return measurements[i].When.After(to) }) if end >= len(measurements) { end = len(measurements) - 1 } if end <= begin { return 0, 0 } sample := measurements[begin:end] if len(sample) == 0 { return 0, 0 } var mo float64 for i := range sample { mo += sample[i].Observed } mo /= float64(len(sample)) var num, denom float64 for i := range sample { d1 := sample[i].Predicted - sample[i].Observed num += d1 * d1 d2 := sample[i].Observed - mo denom += d2 * d2 } return 1 - num/denom, len(sample) }