Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java @ 5838:5aa05a7a34b7
Rename modules to more fitting names.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Thu, 25 Apr 2013 15:23:37 +0200 |
parents | flys-artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java@bd047b71ab37 |
children | 4897a58c8746 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java Thu Apr 25 15:23:37 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 :