comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java @ 9176:1614cb14308f

Work on calculations for S-Info flood duration workflow
author mschaefer
date Mon, 25 Jun 2018 19:21:11 +0200
parents
children a4121ec450d6
comparison
equal deleted inserted replaced
9175:34dc0163ad2d 9176:1614cb14308f
1 /** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
2 * Software engineering by
3 * Björnsen Beratende Ingenieure GmbH
4 * Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
5 *
6 * This file is Free Software under the GNU AGPL (>=v3)
7 * and comes with ABSOLUTELY NO WARRANTY! Check out the
8 * documentation coming with Dive4Elements River for details.
9 */
10 package org.dive4elements.river.artifacts.sinfo.common;
11
12 import org.apache.commons.lang.math.DoubleRange;
13 import org.apache.commons.math.FunctionEvaluationException;
14 import org.apache.commons.math.analysis.UnivariateRealFunction;
15 import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
16 import org.dive4elements.river.artifacts.model.Calculation;
17 import org.dive4elements.river.model.Gauge;
18 import org.dive4elements.river.model.MainValue;
19 import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
20
21 import gnu.trove.TDoubleArrayList;
22
23 /**
24 * Loading and search/interpolate the duration main values of a gauge
25 *
26 * @author Matthias Schäfer
27 *
28 */
29 public final class GaugeDurationValuesFinder {
30
31 /***** FIELDS *****/
32
33 // private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class);
34
35 private final Gauge gauge;
36
37 private Calculation problems;
38
39 private UnivariateRealFunction qInterpolator;
40
41 private DoubleRange qRange;
42
43 private UnivariateRealFunction durInterpolator;
44
45 private DoubleRange durRange;
46
47 private final String approxPrefix = "ca."; // "\u2248" geht wohl nicht
48
49
50 /***** CONSTRUCTORS *****/
51
52 private GaugeDurationValuesFinder(final Gauge gauge, final Calculation problems) {
53 this.gauge = gauge;
54 this.problems = problems;
55 final TDoubleArrayList qs = new TDoubleArrayList();
56 final TDoubleArrayList durs = new TDoubleArrayList();
57 for (final MainValue v : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.DURATION)) {
58 qs.add(v.getValue().doubleValue());
59 durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
60 }
61 try {
62 this.qInterpolator = new LinearInterpolator().interpolate(qs.toNativeArray(), durs.toNativeArray());
63 this.qRange = new DoubleRange(qs.get(0), qs.get(qs.size() - 1));
64 }
65 catch (final Exception e) {
66 this.qInterpolator = null;
67 this.qRange = null;
68 }
69 qs.clear();
70 durs.clear();
71 for (final MainValue v : MainValue.getDurationDischargesOfGauge(gauge)) {
72 durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
73 qs.add(v.getValue().doubleValue());
74 }
75 try {
76 this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray());
77 this.durRange = new DoubleRange(durs.get(0), durs.get(durs.size() - 1));
78 }
79 catch (final Exception e) {
80 this.durInterpolator = null;
81 this.durRange = null;
82 }
83 if (((this.qInterpolator == null) || (this.durInterpolator == null)) && (this.problems != null)) {
84 this.problems.addProblem("gauge_duration.missing", gauge.getName());
85 // Report only once
86 this.problems = null;
87 }
88 }
89
90
91 /***** METHODS *****/
92
93 /**
94 * Loads the the discharge-duration table of a gauge (GAUGE.glt)
95 *
96 * @return The main values finder of a a gauge, or null
97 */
98 public static GaugeDurationValuesFinder loadValues(final Gauge gauge, final Calculation problems) {
99 return new GaugeDurationValuesFinder(gauge, problems);
100 }
101
102 /**
103 * If this provider may return valid data at all.
104 */
105 public boolean isValid() {
106 return (this.qInterpolator != null);
107 }
108
109 /**
110 * Discharge for a duration
111 *
112 * @return Q, or NegInf for duration less than all, or PosInf for duration greater then all, or NaN in case of exception
113 */
114 public double getDischarge(final int duration) {
115 try {
116 if (this.durInterpolator == null)
117 return Double.NaN;
118 else if (duration < this.durRange.getMinimumDouble())
119 return Double.NEGATIVE_INFINITY;
120 else if (duration > this.durRange.getMaximumDouble())
121 return Double.POSITIVE_INFINITY;
122 else
123 return this.durInterpolator.value(duration);
124 }
125 catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
126 // ignore exception because this can/will happen regularly
127 return Double.NaN;
128 }
129 }
130
131 /**
132 * Duration for a discharge
133 *
134 * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or -1 in case of exception
135 */
136 public double getDuration(final double q) {
137 try {
138 if (this.qInterpolator == null)
139 return -1;
140 else if (q < this.qRange.getMinimumDouble())
141 return 0;
142 else if (q > this.qRange.getMaximumDouble())
143 return 365;
144 else
145 return this.qInterpolator.value(q);
146 }
147 catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
148 // ignore exception because this can/will happen regularly
149 return -1;
150 }
151 }
152 }

http://dive4elements.wald.intevation.org