[Dive4elements-commits] [PATCH] Partial rewrite of historical discharge curves. Needs testing
Wald Commits
scm-commit at wald.intevation.org
Fri May 10 10:47:00 CEST 2013
# HG changeset patch
# User Sascha L. Teichmann <teichmann at intevation.de>
# 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<DischargeTable> 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<DischargeTable> 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<DischargeTable> fetchDischargeTables(Gauge gauge) {
- List<DischargeTable> relevant = new ArrayList<DischargeTable>();
+
List<DischargeTable> all = gauge.getDischargeTables();
+ List<DischargeTable> relevant = new ArrayList<DischargeTable>(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();
+ long dtStart = ti.getStartTime().getTime();
+ long dtStop = ti.getStopTime() != null
+ ? ti.getStopTime().getTime()
+ : System.currentTimeMillis();
- 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;
- }
-
- log.debug("DischargeTable not in range: " + start + " -> " + stop);
-
- return false;
+ return !(timerange[1] < dtStart || timerange[0] > dtStop);
}
- 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) {
+ protected WQKms[] prepareWQData(List<DischargeTable> 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<DischargeTable> dts) {
- List<WQTimerange> wqts = new ArrayList<WQTimerange>(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<DischargeTable> dts,
+ ValuesCache vc
+ ) {
+ List<HistoricalWQTimerange> wqts =
+ new ArrayList<HistoricalWQTimerange>(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<DischargeTable> dts) {
- List<HistoricalWQTimerange> wqts = new ArrayList<HistoricalWQTimerange>(
- 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<Integer, double[][]> cache;
+
+ ValuesCache() {
+ cache = new HashMap<Integer, double [][]>();
+ }
+
+ 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) {
More information about the Dive4elements-commits
mailing list