Mercurial > dive4elements > river
view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java @ 5498:d459a885c51f
Schema change: make sq_relation_value.qmax NOT NULL and more informative messages in parser
author | Tom Gottfried <tom.gottfried@intevation.de> |
---|---|
date | Thu, 28 Mar 2013 14:02:52 +0100 |
parents | 1b73b731f7bd |
children |
line wrap: on
line source
package de.intevation.flys.artifacts.model; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import org.apache.log4j.Logger; import de.intevation.flys.model.DischargeTable; import de.intevation.flys.model.Gauge; import de.intevation.flys.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 :