Mercurial > gemma
comparison 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 |
comparison
equal
deleted
inserted
replaced
2740:85de42146bdb | 2741:87aed4f9b1b8 |
---|---|
1 // This is Free Software under GNU Affero General Public License v >= 3.0 | |
2 // without warranty, see README.md and license for details. | |
3 // | |
4 // SPDX-License-Identifier: AGPL-3.0-or-later | |
5 // License-Filename: LICENSES/AGPL-3.0.txt | |
6 // | |
7 // Copyright (C) 2019 by via donau | |
8 // – Österreichische Wasserstraßen-Gesellschaft mbH | |
9 // Software engineering by Intevation GmbH | |
10 // | |
11 // Author(s): | |
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de> | |
13 | |
14 package common | |
15 | |
16 import ( | |
17 "sort" | |
18 "time" | |
19 ) | |
20 | |
21 type NSMeasurement struct { | |
22 When time.Time | |
23 Predicted float64 | |
24 Observed float64 | |
25 } | |
26 | |
27 func NashSutcliffeSort(measurements []NSMeasurement) { | |
28 sort.Slice(measurements, func(i, j int) bool { | |
29 return measurements[i].When.Before(measurements[j].When) | |
30 }) | |
31 } | |
32 | |
33 func NashSutcliffe(measurements []NSMeasurement, from, to time.Time) (float64, int) { | |
34 | |
35 if len(measurements) == 0 { | |
36 return 0, 0 | |
37 } | |
38 | |
39 if to.Before(from) { | |
40 from, to = to, from | |
41 } | |
42 | |
43 begin := sort.Search(len(measurements), func(i int) bool { | |
44 return !measurements[i].When.Before(from) | |
45 }) | |
46 if begin >= len(measurements) { | |
47 return 0, 0 | |
48 } | |
49 | |
50 end := sort.Search(len(measurements), func(i int) bool { | |
51 return measurements[i].When.After(to) | |
52 }) | |
53 if end >= len(measurements) { | |
54 end = len(measurements) - 1 | |
55 } | |
56 if end <= begin { | |
57 return 0, 0 | |
58 } | |
59 sample := measurements[begin:end] | |
60 | |
61 if len(sample) == 0 { | |
62 return 0, 0 | |
63 } | |
64 | |
65 var mo float64 | |
66 for i := range sample { | |
67 mo += sample[i].Observed | |
68 } | |
69 | |
70 mo /= float64(len(sample)) | |
71 | |
72 var num, denom float64 | |
73 for i := range sample { | |
74 d1 := sample[i].Predicted - sample[i].Observed | |
75 num += d1 * d1 | |
76 d2 := sample[i].Observed - mo | |
77 denom += d2 * d2 | |
78 } | |
79 | |
80 return 1 - num/denom, len(sample) | |
81 } |