comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java @ 9358:8eddc2393750

Fixed: S-Info flood duration Q-D interpolation for non monotonous Q values, NaN instead of -1 in error cases
author mschaefer
date Wed, 01 Aug 2018 13:20:38 +0200
parents 9b16f58c62a7
children
comparison
equal deleted inserted replaced
9357:5ce50640688c 9358:8eddc2393750
11 11
12 import org.apache.commons.lang.math.DoubleRange; 12 import org.apache.commons.lang.math.DoubleRange;
13 import org.apache.commons.math.FunctionEvaluationException; 13 import org.apache.commons.math.FunctionEvaluationException;
14 import org.apache.commons.math.analysis.UnivariateRealFunction; 14 import org.apache.commons.math.analysis.UnivariateRealFunction;
15 import org.apache.commons.math.analysis.interpolation.LinearInterpolator; 15 import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
16 import org.apache.log4j.Logger;
16 import org.dive4elements.river.artifacts.model.Calculation; 17 import org.dive4elements.river.artifacts.model.Calculation;
17 import org.dive4elements.river.model.Gauge; 18 import org.dive4elements.river.model.Gauge;
18 import org.dive4elements.river.model.MainValue; 19 import org.dive4elements.river.model.MainValue;
19 import org.dive4elements.river.model.MainValueType.MainValueTypeKey; 20 import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
20 21
28 */ 29 */
29 public final class GaugeDurationValuesFinder { 30 public final class GaugeDurationValuesFinder {
30 31
31 /***** FIELDS *****/ 32 /***** FIELDS *****/
32 33
33 // private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class); 34 private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class);
34 35
35 private final Gauge gauge; 36 private final Gauge gauge;
36 37
37 private Calculation problems; 38 private Calculation problems;
38 39
55 final TDoubleArrayList durs = new TDoubleArrayList(); 56 final TDoubleArrayList durs = new TDoubleArrayList();
56 for (final MainValue v : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.DURATION)) { 57 for (final MainValue v : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.DURATION)) {
57 qs.add(v.getValue().doubleValue()); 58 qs.add(v.getValue().doubleValue());
58 durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue()); 59 durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
59 } 60 }
61 // Merge out-of-order Qs
62 final TDoubleArrayList q1s = new TDoubleArrayList();
63 final TDoubleArrayList dur1s = new TDoubleArrayList();
64 boolean writeWarn = true;
65 int cnt = 0;
66 int i = -1;
67 while ((i + 1) <= qs.size() - 1) {
68 i++;
69 if ((i == 0) || (qs.getQuick(i - 1) < qs.getQuick(i) - 0.001)) {
70 q1s.add(qs.getQuick(i));
71 dur1s.add(durs.getQuick(i));
72 cnt = 1;
73 }
74 else {
75 q1s.set(q1s.size() - 1, (q1s.getQuick(q1s.size() - 1) * cnt + qs.getQuick(i)) / (cnt + 1));
76 dur1s.set(dur1s.size() - 1, (dur1s.getQuick(dur1s.size() - 1) * cnt + durs.getQuick(i)) / (cnt + 1));
77 cnt++;
78 if (writeWarn) {
79 log.warn("Nicht streng monotone Q in D(Q) des Pegels " + gauge.getName());
80 writeWarn = false;
81 }
82 }
83 }
60 // Build the duration-by-Q interpolator 84 // Build the duration-by-Q interpolator
61 try { 85 try {
62 this.qInterpolator = new LinearInterpolator().interpolate(qs.toNativeArray(), durs.toNativeArray()); 86 this.qInterpolator = new LinearInterpolator().interpolate(q1s.toNativeArray(), dur1s.toNativeArray());
63 this.qRange = new DoubleRange(qs.get(0), qs.get(qs.size() - 1)); 87 this.qRange = new DoubleRange(q1s.getQuick(0), q1s.getQuick(q1s.size() - 1));
64 } 88 }
65 catch (final Exception e) { 89 catch (final Exception e) {
66 this.qInterpolator = null; 90 this.qInterpolator = null;
67 this.qRange = null; 91 this.qRange = null;
68 } 92 }
74 qs.add(v.getValue().doubleValue()); 98 qs.add(v.getValue().doubleValue());
75 } 99 }
76 // Build the Q-by-duration interpolator 100 // Build the Q-by-duration interpolator
77 try { 101 try {
78 this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray()); 102 this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray());
79 this.durRange = new DoubleRange(durs.get(0), durs.get(durs.size() - 1)); 103 this.durRange = new DoubleRange(durs.getQuick(0), durs.getQuick(durs.size() - 1));
80 } 104 }
81 catch (final Exception e) { 105 catch (final Exception e) {
82 this.durInterpolator = null; 106 this.durInterpolator = null;
83 this.durRange = null; 107 this.durRange = null;
84 } 108 }
132 } 156 }
133 157
134 /** 158 /**
135 * Duration for a discharge 159 * Duration for a discharge
136 * 160 *
137 * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or -1 in case of exception 161 * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or NaN in case of missing
162 * interpolator or exception
138 */ 163 */
139 public double getDuration(final double q) { 164 public double getDuration(final double q) {
140 try { 165 try {
141 if (this.qInterpolator == null) 166 if (this.qInterpolator == null)
142 return -1; 167 return Double.NaN;
143 else if (q < this.qRange.getMinimumDouble()) 168 else if (q < this.qRange.getMinimumDouble())
144 return 0; 169 return 0;
145 else if (q > this.qRange.getMaximumDouble()) 170 else if (q > this.qRange.getMaximumDouble())
146 return 365; 171 return 365;
147 else 172 else
148 return this.qInterpolator.value(q); 173 return this.qInterpolator.value(q);
149 } 174 }
150 catch (@SuppressWarnings("unused") final FunctionEvaluationException e) { 175 catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
151 // ignore exception because this can/will happen regularly 176 // ignore exception because this can/will happen regularly
152 return -1; 177 return Double.NaN;
153 } 178 }
154 } 179 }
155 } 180 }

http://dive4elements.wald.intevation.org