changeset 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 (2018-08-01)
parents 5ce50640688c
children df6f1b5806f6
files artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java
diffstat 1 files changed, 32 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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

http://dive4elements.wald.intevation.org