diff flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java @ 5831:bd047b71ab37

Repaired internal references
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 25 Apr 2013 12:06:39 +0200
parents flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java@1b73b731f7bd
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java	Thu Apr 25 12:06:39 2013 +0200
@@ -0,0 +1,347 @@
+package org.dive4elements.river.artifacts.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.dive4elements.river.model.DischargeTable;
+import org.dive4elements.river.model.Gauge;
+import org.dive4elements.river.model.TimeInterval;
+
+
+/**
+ * Historical Discharge Calculation.
+ * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
+ */
+public class Calculation6 extends Calculation {
+
+    private static final Logger logger = Logger.getLogger(Calculation6.class);
+
+    private int mode;
+    private long[] timerange;
+    private double[] values;
+
+    public static final int MODE_W = 0;
+    public static final int MODE_Q = 1;
+
+    public static final double SCALE = 1d;
+
+    public Calculation6(int mode, long[] timerange, double[] values) {
+        this.mode = mode;
+        this.timerange = timerange;
+        this.values = values;
+    }
+
+    public CalculationResult calculate(Gauge gauge) {
+        if (!checkParameters() || gauge == null) {
+            logger.warn("Parameters not valid for calculation.");
+
+            return null;
+        }
+
+        if (logger.isDebugEnabled()) {
+            debug();
+        }
+
+        DischargeTable refTable = fetchReferenceTable(gauge);
+        List<DischargeTable> dts = fetchDischargeTables(gauge);
+
+        int numTables = dts.size();
+
+        logger.debug("Take " + numTables + " into account.");
+
+        if (numTables == 0) {
+            addProblem("cannot.find.hist.q.tables");
+        }
+
+        WQTimerange[] wqt = prepareTimerangeData(refTable, dts);
+        WQKms[] wqs = prepareWQData(dts);
+
+        logger.debug("Number of calculation results: " + wqt.length);
+
+        return new CalculationResult(new HistoricalDischargeData(wqt, wqs),
+            this);
+    }
+
+    protected boolean checkParameters() {
+        if (!(mode == MODE_W || mode == MODE_Q)) {
+            logger.warn("Invalid mode '" + mode + "' for calculation.");
+            return false;
+        }
+
+        if (timerange == null || timerange.length < 2) {
+            logger.warn("Invalid timerange for calculation.");
+            return false;
+        }
+
+        if (values == null || values.length == 0) {
+            logger.warn("No values for W or Q specified.");
+            return false;
+        }
+
+        return true;
+    }
+
+    protected DischargeTable fetchReferenceTable(Gauge gauge) {
+        return gauge.fetchMasterDischargeTable();
+    }
+
+    protected List<DischargeTable> fetchDischargeTables(Gauge gauge) {
+        List<DischargeTable> relevant = new ArrayList<DischargeTable>();
+        List<DischargeTable> all = gauge.getDischargeTables();
+
+        for (DischargeTable dt : all) {
+            if (isDischargeTableRelevant(dt)) {
+                relevant.add(dt);
+            }
+        }
+
+        return relevant;
+    }
+
+    /** True if timerange of given discharge table overlaps with timerange. */
+    protected boolean isDischargeTableRelevant(DischargeTable dt) {
+        TimeInterval ti = dt.getTimeInterval();
+
+        if (dt.getKind() == Gauge.MASTER_DISCHARGE_TABLE || ti == null) {
+            return false;
+        }
+
+        Date start = ti.getStartTime();
+        long startTime = start.getTime();
+
+        if (startTime >= timerange[0] && startTime <= timerange[1]) {
+            return true;
+        }
+
+        Date stop = ti.getStopTime();
+        long stopTime = stop != null ? stop.getTime() : -1l;
+
+        if (stopTime >= timerange[0] && stopTime <= timerange[1]) {
+            return true;
+        }
+
+        logger.debug("DischargeTable not in range: " + start + " -> " + stop);
+
+        return false;
+    }
+
+    protected WQTimerange[] prepareTimerangeData(DischargeTable refTable,
+        List<DischargeTable> dts) {
+        if (refTable == null) {
+            addProblem("cannot.find.hist.q.reftable");
+            return prepareSimpleData(dts);
+        }
+        else {
+            return prepareData(refTable, dts);
+        }
+    }
+
+    protected WQKms[] prepareWQData(List<DischargeTable> dts) {
+        WQKms[] wqs = new WQKms[dts.size()];
+
+        int idx = 0;
+
+        for (DischargeTable dt : dts) {
+            double[][] values = null;
+
+            if (dt.getKind() == DischargeTables.MASTER) {
+                values = DischargeTables.loadDischargeTableValues(dt,
+                    DischargeTables.MASTER_SCALE);
+
+            }
+            else {
+                values = DischargeTables.loadDischargeTableValues(dt,
+                    DischargeTables.HISTORICAL_SCALE);
+
+            }
+
+            wqs[idx++] = prepareWQ(dt, values);
+        }
+
+        return wqs;
+    }
+
+    protected WQKms prepareWQ(DischargeTable dt, double[][] values) {
+        double km = dt.getGauge().getStation().doubleValue();
+
+        double[] kms = new double[values[0].length];
+        Arrays.fill(kms, km);
+
+        return new HistoricalWQKms(kms, values[0], values[1],
+            String.valueOf(km), dt.getTimeInterval());
+    }
+
+    /** Without reference. */
+    protected WQTimerange[] prepareSimpleData(List<DischargeTable> dts) {
+        List<WQTimerange> wqts = new ArrayList<WQTimerange>(values.length);
+
+        for (double value : values) {
+            logger.debug("Prepare data for value: " + value);
+
+            String name = mode == MODE_W ? "W=" + value : "Q=" + value;
+            WQTimerange wqt = null;
+
+            for (DischargeTable dt : dts) {
+                Date[] ti = prepareTimeInterval(dt);
+                Timerange t = new Timerange(ti[0], ti[1]);
+                double w;
+                double q;
+
+                if (mode == MODE_W) {
+                    w = value;
+                    q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE);
+
+                    if (Double.isNaN(q)) {
+                        logger.warn("Cannot find Q for W: " + w);
+                        addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]);
+                        continue;
+                    }
+                }
+                else {
+                    q = value;
+                    w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE);
+                }
+
+                logger.debug("Q=" + q + " | W=" + w);
+
+                if (wqt == null) {
+                    wqt = new WQTimerange(name);
+                }
+
+                wqt.add(w, q, t);
+            }
+
+            if (wqt != null) {
+                wqts.add(wqt);
+            }
+        }
+
+        return wqts.toArray(new WQTimerange[wqts.size()]);
+    }
+
+    /** With reference. */
+    protected HistoricalWQTimerange[] prepareData(DischargeTable refTable,
+        List<DischargeTable> dts) {
+        List<HistoricalWQTimerange> wqts = new ArrayList<HistoricalWQTimerange>(
+            values.length);
+
+        for (double value : values) {
+            logger.debug("Prepare data plus diff for value: " + value);
+
+            String name = mode == MODE_W ? "W=" + value : "Q=" + value;
+            HistoricalWQTimerange wqt = null;
+
+            double ref;
+            double diff;
+
+            if (refTable != null && mode == MODE_W) {
+                ref = findValueForW(refTable, value,
+                    DischargeTables.MASTER_SCALE);
+            }
+            else if (refTable != null) {
+                ref = findValueForQ(refTable, value,
+                    DischargeTables.MASTER_SCALE);
+            }
+            else {
+                ref = Double.NaN;
+            }
+
+            for (DischargeTable dt : dts) {
+                Date[] ti = prepareTimeInterval(dt);
+
+                Timerange t = new Timerange(ti[0], ti[1]);
+                double w;
+                double q;
+
+                if (mode == MODE_W) {
+                    w = value;
+                    q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE);
+
+                    if (Double.isNaN(q)) {
+                        logger.warn("Cannot find Q for W: " + w);
+                        addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]);
+                        continue;
+                    }
+
+                    diff = ref - q;
+                }
+                else {
+                    q = value;
+                    w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE);
+
+                    if (Double.isNaN(w)) {
+                        logger.warn("Cannot find W for Q: " + q);
+                        addProblem("cannot.find.hist.w.for.q", q, ti[0], ti[1]);
+                        continue;
+                    }
+                    diff = ref - w;
+                }
+
+                logger.debug("Q=" + q + " | W=" + w + " | Ref = " + ref);
+
+                if (wqt == null) {
+                    wqt = new HistoricalWQTimerange(name);
+                }
+
+                wqt.add(w, q, diff, t);
+            }
+
+            if (wqt != null) {
+                wqts.add(wqt);
+            }
+        }
+
+        return (HistoricalWQTimerange[]) wqts
+            .toArray(new HistoricalWQTimerange[wqts.size()]);
+    }
+
+    /** Returns discharge table interval as Date[]. */
+    protected Date[] prepareTimeInterval(DischargeTable dt) {
+        TimeInterval ti = dt.getTimeInterval();
+
+        Date start = ti.getStartTime();
+        Date end = ti.getStopTime();
+
+        if (end == null) {
+            logger.warn("TimeInterval has no stop time set!");
+
+            end = new Date();
+        }
+
+        return new Date[] { start, end };
+    }
+
+    protected double findValueForW(DischargeTable dt, double w, double scale) {
+        double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale);
+        double[] qs = DischargeTables.getQsForW(vs, w);
+        return qs.length == 0 ? Double.NaN : qs[0];
+    }
+
+    protected double findValueForQ(DischargeTable dt, double q, double scale) {
+        double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale);
+        double[] ws = DischargeTables.getWsForQ(vs, q);
+
+        return ws.length == 0 ? Double.NaN : ws[0];
+    }
+
+    /**
+     * Writes the parameters used for this calculation to logger.
+     */
+    public void debug() {
+        StringBuilder sb = new StringBuilder();
+        for (double value : values) {
+            sb.append(String.valueOf(value) + " ");
+        }
+
+        logger.debug("========== Calculation6 ==========");
+        logger.debug("   Mode:         " + mode);
+        logger.debug("   Timerange:    " + timerange[0] + " - " + timerange[1]);
+        logger.debug("   Input values: " + sb.toString());
+        logger.debug("==================================");
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org