# HG changeset patch # User Sascha L. Teichmann # Date 1368175616 -7200 # Node ID d861efa13272af2a71f196a41dc8b6f2d92880dc # Parent 55687a5062968a8a4ba0d9b41d5a6db9debf4d5d Partial rewrite of historical discharge curves. Needs testing. diff -r 55687a506296 -r d861efa13272 artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java Fri May 10 10:02:27 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/Calculation6.java Fri May 10 10:46:56 2013 +0200 @@ -11,7 +11,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; @@ -87,6 +89,11 @@ this.officialGaugeNumber = officialGaugeNumber; } + protected CalculationResult error(String msg) { + addProblem(msg); + return new CalculationResult(new HistoricalDischargeData(), this); + } + public CalculationResult calculate() { if (hasProblems()) { log.warn("Parameters not valid for calculation."); @@ -96,43 +103,73 @@ Gauge gauge = Gauge.getGaugeByOfficialNumber(officialGaugeNumber); if (gauge == null) { // TODO: i18n - addProblem("hist.discharge.gauge.not.found"); - return null; + return error("hist.discharge.gauge.not.found"); } if (log.isDebugEnabled()) { debug(); } - DischargeTable refTable = fetchReferenceTable(gauge); List dts = fetchDischargeTables(gauge); - - int numTables = dts.size(); - - log.debug("Take " + numTables + " into account."); - - if (numTables == 0) { - addProblem("cannot.find.hist.q.tables"); + if (dts.isEmpty()) { + return error("cannot.find.hist.q.tables"); } - WQTimerange[] wqt = prepareTimerangeData(refTable, dts); - WQKms[] wqs = prepareWQData(dts); + DischargeTable refTable = fetchReferenceTable(dts); - log.debug("Number of calculation results: " + wqt.length); + boolean debug = log.isDebugEnabled(); + + if (debug) { + log.debug("Take " + dts.size() + " into account."); + } + + ValuesCache vc = new ValuesCache(); + + WQTimerange [] wqt = prepareData(refTable, dts, vc); + WQKms [] wqs = prepareWQData(dts, vc); + + if (debug) { + log.debug("Number of calculation results: " + wqt.length); + } return new CalculationResult(new HistoricalDischargeData(wqt, wqs), this); } - protected DischargeTable fetchReferenceTable(Gauge gauge) { - return gauge.fetchMasterDischargeTable(); + /** The youngest discharge table of the selected set is the reference */ + protected DischargeTable fetchReferenceTable(List dts) { + DischargeTable ref = null; + long now = System.currentTimeMillis(); + for (DischargeTable dt: dts) { + if (ref == null) { + ref = dt; + } + else { + TimeInterval cti = dt.getTimeInterval(); + TimeInterval rti = ref.getTimeInterval(); + + long ct = cti.getStopTime() != null + ? cti.getStopTime().getTime() + : now; + long rt = rti.getStopTime() != null + ? rti.getStopTime().getTime() + : now; + + if (ct > rt) { + ref = dt; + } + + } + } + return ref; } protected List fetchDischargeTables(Gauge gauge) { - List relevant = new ArrayList(); + List all = gauge.getDischargeTables(); + List relevant = new ArrayList(all.size()); - for (DischargeTable dt : all) { + for (DischargeTable dt: all) { if (isDischargeTableRelevant(dt)) { relevant.add(dt); } @@ -143,62 +180,27 @@ /** 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; - } + long dtStart = ti.getStartTime().getTime(); + long dtStop = ti.getStopTime() != null + ? ti.getStopTime().getTime() + : System.currentTimeMillis(); - Date stop = ti.getStopTime(); - long stopTime = stop != null ? stop.getTime() : -1l; - - if (stopTime >= timerange[0] && stopTime <= timerange[1]) { - return true; - } - - log.debug("DischargeTable not in range: " + start + " -> " + stop); - - return false; + return !(timerange[1] < dtStart || timerange[0] > dtStop); } - protected WQTimerange[] prepareTimerangeData(DischargeTable refTable, - List dts) { - if (refTable == null) { - addProblem("cannot.find.hist.q.reftable"); - return prepareSimpleData(dts); - } - else { - return prepareData(refTable, dts); - } - } - - protected WQKms[] prepareWQData(List dts) { + protected WQKms[] prepareWQData(List dts, ValuesCache vc) { 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); + for (int i = 0, N = wqs.length; i < N; ++i) { + DischargeTable dt = dts.get(i); + wqs[i] = prepareWQ(dt, vc.getValues(dts.get(i))); } return wqs; @@ -214,96 +216,49 @@ String.valueOf(km), dt.getTimeInterval()); } - /** Without reference. */ - protected WQTimerange[] prepareSimpleData(List dts) { - List wqts = new ArrayList(values.length); + protected String name(double value) { + return mode == EvaluationMode.W.getMode() + ? "W=" + value + : "Q=" + value; + } - for (double value : values) { - log.debug("Prepare data for value: " + value); + /** With reference. */ + protected HistoricalWQTimerange[] prepareData( + DischargeTable refTable, + List dts, + ValuesCache vc + ) { + List wqts = + new ArrayList(values.length); - String name = mode == EvaluationMode.W.getMode() - ? "W=" + value - : "Q=" + value; + boolean debug = log.isDebugEnabled(); - WQTimerange wqt = null; + for (double value: values) { + if (debug) { + log.debug("Prepare data plus diff for value: " + value); + } + + double ref = mode == EvaluationMode.W.getMode() + ? vc.findValueForW(refTable, value) + : vc.findValueForQ(refTable, value); + + if (Double.isNaN(ref)) { + addProblem("hist.discharge.bo.value.in.ref", value); + continue; + } + + String name = name(value); + HistoricalWQTimerange wqt = null; for (DischargeTable dt : dts) { Date[] ti = prepareTimeInterval(dt); Timerange t = new Timerange(ti[0], ti[1]); double w; double q; + double diff; if (mode == EvaluationMode.W.getMode()) { - w = value; - q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE); - - if (Double.isNaN(q)) { - log.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); - } - - log.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 dts) { - List wqts = new ArrayList( - values.length); - - for (double value : values) { - log.debug("Prepare data plus diff for value: " + value); - - String name = mode == EvaluationMode.W.getMode() - ? "W=" + value - : "Q=" + value; - HistoricalWQTimerange wqt = null; - - double ref; - double diff; - - if (refTable != null && mode == EvaluationMode.W.getMode()) { - 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 == EvaluationMode.W.getMode()) { - w = value; - q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE); + q = vc.findValueForW(dt, w = value); if (Double.isNaN(q)) { log.warn("Cannot find Q for W: " + w); @@ -314,8 +269,7 @@ diff = ref - q; } else { - q = value; - w = findValueForQ(dt, q, DischargeTables.HISTORICAL_SCALE); + w = vc.findValueForQ(dt, q = value); if (Double.isNaN(w)) { log.warn("Cannot find W for Q: " + q); @@ -325,7 +279,9 @@ diff = ref - w; } - log.debug("Q=" + q + " | W=" + w + " | Ref = " + ref); + if (debug) { + log.debug("Q=" + q + " | W=" + w + " | Ref = " + ref); + } if (wqt == null) { wqt = new HistoricalWQTimerange(name); @@ -339,8 +295,8 @@ } } - return (HistoricalWQTimerange[]) wqts - .toArray(new HistoricalWQTimerange[wqts.size()]); + return (HistoricalWQTimerange[])wqts.toArray( + new HistoricalWQTimerange[wqts.size()]); } /** Returns discharge table interval as Date[]. */ @@ -359,18 +315,39 @@ 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); + /** Helper to avoid redundant loading of discharge table values. */ + private static final class ValuesCache { - return ws.length == 0 ? Double.NaN : ws[0]; - } + private Map cache; + + ValuesCache() { + cache = new HashMap(); + } + + double [][] getValues(DischargeTable dt) { + Integer id = dt.getId(); + double [][] vs = cache.get(id); + if (vs == null) { + vs = DischargeTables.loadDischargeTableValues( + dt, DischargeTables.HISTORICAL_SCALE); + cache.put(id, vs); + } + return vs; + } + + private static double firstOrNaN(double [] vs) { + return vs.length > 0 ? vs[0] : Double.NaN; + } + + double findValueForW(DischargeTable dt, double w) { + return firstOrNaN(DischargeTables.getQsForW(getValues(dt), w)); + } + + double findValueForQ(DischargeTable dt, double q) { + return firstOrNaN(DischargeTables.getWsForQ(getValues(dt), q)); + } + } // class ValuesCache /** * Writes the parameters used for this calculation to log. diff -r 55687a506296 -r d861efa13272 artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeData.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeData.java Fri May 10 10:02:27 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/HistoricalDischargeData.java Fri May 10 10:46:56 2013 +0200 @@ -17,6 +17,8 @@ private WQTimerange[] wqTimeranges; public HistoricalDischargeData() { + wqs = new WQKms[0]; + wqTimeranges = new WQTimerange[0]; } public HistoricalDischargeData(WQTimerange[] wqTimeranges, WQKms[] wqs) {