diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java	Mon Jun 25 19:21:11 2018 +0200
@@ -0,0 +1,152 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.artifacts.sinfo.common;
+
+import org.apache.commons.lang.math.DoubleRange;
+import org.apache.commons.math.FunctionEvaluationException;
+import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
+import org.dive4elements.river.artifacts.model.Calculation;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
+
+import gnu.trove.TDoubleArrayList;
+
+/**
+ * Loading and search/interpolate the duration main values of a gauge
+ *
+ * @author Matthias Schäfer
+ *
+ */
+public final class GaugeDurationValuesFinder {
+
+    /***** FIELDS *****/
+
+    // private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class);
+
+    private final Gauge gauge;
+
+    private Calculation problems;
+
+    private UnivariateRealFunction qInterpolator;
+
+    private DoubleRange qRange;
+
+    private UnivariateRealFunction durInterpolator;
+
+    private DoubleRange durRange;
+
+    private final String approxPrefix = "ca."; // "\u2248" geht wohl nicht
+
+
+    /***** CONSTRUCTORS *****/
+
+    private GaugeDurationValuesFinder(final Gauge gauge, final Calculation problems) {
+        this.gauge = gauge;
+        this.problems = problems;
+        final TDoubleArrayList qs = new TDoubleArrayList();
+        final TDoubleArrayList durs = new TDoubleArrayList();
+        for (final MainValue v : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.DURATION)) {
+            qs.add(v.getValue().doubleValue());
+            durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
+        }
+        try {
+            this.qInterpolator = new LinearInterpolator().interpolate(qs.toNativeArray(), durs.toNativeArray());
+            this.qRange = new DoubleRange(qs.get(0), qs.get(qs.size() - 1));
+        }
+        catch (final Exception e) {
+            this.qInterpolator = null;
+            this.qRange = null;
+        }
+        qs.clear();
+        durs.clear();
+        for (final MainValue v : MainValue.getDurationDischargesOfGauge(gauge)) {
+            durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
+            qs.add(v.getValue().doubleValue());
+        }
+        try {
+            this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray());
+            this.durRange = new DoubleRange(durs.get(0), durs.get(durs.size() - 1));
+        }
+        catch (final Exception e) {
+            this.durInterpolator = null;
+            this.durRange = null;
+        }
+        if (((this.qInterpolator == null) || (this.durInterpolator == null)) && (this.problems != null)) {
+            this.problems.addProblem("gauge_duration.missing", gauge.getName());
+            // Report only once
+            this.problems = null;
+        }
+    }
+
+
+    /***** METHODS *****/
+
+    /**
+     * Loads the the discharge-duration table of a gauge (GAUGE.glt)
+     *
+     * @return The main values finder of a a gauge, or null
+     */
+    public static GaugeDurationValuesFinder loadValues(final Gauge gauge, final Calculation problems) {
+        return new GaugeDurationValuesFinder(gauge, problems);
+    }
+
+    /**
+     * If this provider may return valid data at all.
+     */
+    public boolean isValid() {
+        return (this.qInterpolator != null);
+    }
+
+    /**
+     * Discharge for a duration
+     *
+     * @return Q, or NegInf for duration less than all, or PosInf for duration greater then all, or NaN in case of exception
+     */
+    public double getDischarge(final int duration) {
+        try {
+            if (this.durInterpolator == null)
+                return Double.NaN;
+            else if (duration < this.durRange.getMinimumDouble())
+                return Double.NEGATIVE_INFINITY;
+            else if (duration > this.durRange.getMaximumDouble())
+                return Double.POSITIVE_INFINITY;
+            else
+                return this.durInterpolator.value(duration);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return Double.NaN;
+        }
+    }
+
+    /**
+     * 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
+     */
+    public double getDuration(final double q) {
+        try {
+            if (this.qInterpolator == null)
+                return -1;
+            else if (q < this.qRange.getMinimumDouble())
+                return 0;
+            else if (q > this.qRange.getMaximumDouble())
+                return 365;
+            else
+                return this.qInterpolator.value(q);
+        }
+        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
+            // ignore exception because this can/will happen regularly
+            return -1;
+        }
+    }
+}
\ No newline at end of file

http://dive4elements.wald.intevation.org