# HG changeset patch # User mschaefer # Date 1533122438 -7200 # Node ID 8eddc2393750fa2fe3517645bce41adaad7d5edb # Parent 5ce50640688c4c16eccd7c3c73003e206dfa7360 Fixed: S-Info flood duration Q-D interpolation for non monotonous Q values, NaN instead of -1 in error cases diff -r 5ce50640688c -r 8eddc2393750 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java Wed Aug 01 13:18:45 2018 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java Wed Aug 01 13:20:38 2018 +0200 @@ -13,6 +13,7 @@ import org.apache.commons.math.FunctionEvaluationException; import org.apache.commons.math.analysis.UnivariateRealFunction; import org.apache.commons.math.analysis.interpolation.LinearInterpolator; +import org.apache.log4j.Logger; import org.dive4elements.river.artifacts.model.Calculation; import org.dive4elements.river.model.Gauge; import org.dive4elements.river.model.MainValue; @@ -30,7 +31,7 @@ /***** FIELDS *****/ - // private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class); + private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class); private final Gauge gauge; @@ -57,10 +58,33 @@ qs.add(v.getValue().doubleValue()); durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue()); } + // Merge out-of-order Qs + final TDoubleArrayList q1s = new TDoubleArrayList(); + final TDoubleArrayList dur1s = new TDoubleArrayList(); + boolean writeWarn = true; + int cnt = 0; + int i = -1; + while ((i + 1) <= qs.size() - 1) { + i++; + if ((i == 0) || (qs.getQuick(i - 1) < qs.getQuick(i) - 0.001)) { + q1s.add(qs.getQuick(i)); + dur1s.add(durs.getQuick(i)); + cnt = 1; + } + else { + q1s.set(q1s.size() - 1, (q1s.getQuick(q1s.size() - 1) * cnt + qs.getQuick(i)) / (cnt + 1)); + dur1s.set(dur1s.size() - 1, (dur1s.getQuick(dur1s.size() - 1) * cnt + durs.getQuick(i)) / (cnt + 1)); + cnt++; + if (writeWarn) { + log.warn("Nicht streng monotone Q in D(Q) des Pegels " + gauge.getName()); + writeWarn = false; + } + } + } // Build the duration-by-Q interpolator try { - this.qInterpolator = new LinearInterpolator().interpolate(qs.toNativeArray(), durs.toNativeArray()); - this.qRange = new DoubleRange(qs.get(0), qs.get(qs.size() - 1)); + this.qInterpolator = new LinearInterpolator().interpolate(q1s.toNativeArray(), dur1s.toNativeArray()); + this.qRange = new DoubleRange(q1s.getQuick(0), q1s.getQuick(q1s.size() - 1)); } catch (final Exception e) { this.qInterpolator = null; @@ -76,7 +100,7 @@ // Build the Q-by-duration interpolator try { this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray()); - this.durRange = new DoubleRange(durs.get(0), durs.get(durs.size() - 1)); + this.durRange = new DoubleRange(durs.getQuick(0), durs.getQuick(durs.size() - 1)); } catch (final Exception e) { this.durInterpolator = null; @@ -134,12 +158,13 @@ /** * Duration for a discharge * - * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or -1 in case of exception + * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or NaN in case of missing + * interpolator or exception */ public double getDuration(final double q) { try { if (this.qInterpolator == null) - return -1; + return Double.NaN; else if (q < this.qRange.getMinimumDouble()) return 0; else if (q > this.qRange.getMaximumDouble()) @@ -149,7 +174,7 @@ } catch (@SuppressWarnings("unused") final FunctionEvaluationException e) { // ignore exception because this can/will happen regularly - return -1; + return Double.NaN; } } } \ No newline at end of file