# HG changeset patch # User Ingo Weinzierl # Date 1328785055 0 # Node ID b8df8d1476badfc3a60b0696d60e884e8cc3d54f # Parent ecb76933362ff167a1f7cf73dabd7c69f1c73967 Compute differences between discharge table values and reference discharge table values in historical discharge curve calculation. flys-artifacts/trunk@3991 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/ChangeLog Thu Feb 09 10:57:35 2012 +0000 @@ -1,3 +1,42 @@ +2012-02-09 Ingo Weinzierl + + * doc/conf/artifacts/winfo.xml: Registered a new facet for difference curves + to the historical discharge output. + + * src/main/java/de/intevation/flys/artifacts/model/HistoricalWQTimerange.java: + New model that is able to store a further double value "diff" besides a W, + Q and a Timerange. + + * src/main/java/de/intevation/flys/artifacts/model/Calculation6.java: Create + new HistoricalWQTimerange instances with difference between the reference + discharge table and the historical discharge tables. + + * src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java: New type + for historical differences. + + * src/main/java/de/intevation/flys/artifacts/model/WQTimerange.java: Cast + Timerange array in getTimeranges(). + + * src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeDifferenceFacet.java: + New Facet for historical discharge difference curves. + + * src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeComputeState.java: + Create new Facets for the difference curves if the processed data are from + type HistoricalWQTimerange. + + * src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveGenerator.java: + Added doOut() path for difference curves. + + * src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveExporter.java: + Increased the size of a double array to be able to get results from + HistoricalWQTimerange. + + * src/main/resources/messages.properties, + src/main/resources/messages_de_DE.properties, + src/main/resources/messages_en.properties, + src/main/resources/messages_de.properties: Added translation for warning + if no reference discharge table was found for the specified gauge. + 2012-02-09 Raimund Renkert Added PDF export to reference curve calculation. diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/doc/conf/artifacts/winfo.xml --- a/flys-artifacts/doc/conf/artifacts/winfo.xml Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/doc/conf/artifacts/winfo.xml Thu Feb 09 10:57:35 2012 +0000 @@ -510,6 +510,7 @@ + diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java Thu Feb 09 10:57:35 2012 +0000 @@ -47,6 +47,7 @@ debug(); } + DischargeTable refTable = fetchReferenceTable(gauge); List dts = fetchDischargeTables(gauge); int numTables = dts.size(); @@ -57,7 +58,7 @@ addProblem("cannot.find.hist.q.tables"); } - WQTimerange[] wqt = prepareCalculationData(dts); + WQTimerange[] wqt = prepareCalculationData(refTable, dts); logger.debug("Number of calculation results: " + wqt.length); @@ -85,6 +86,11 @@ } + protected DischargeTable fetchReferenceTable(Gauge gauge) { + return gauge.fetchMasterDischargeTable(); + } + + protected List fetchDischargeTables(Gauge gauge) { List relevant = new ArrayList(); List all = gauge.getDischargeTables(); @@ -122,15 +128,30 @@ } - protected WQTimerange[] prepareCalculationData(List dts) { - List wqts = new ArrayList(values.length); + protected WQTimerange[] prepareCalculationData( + DischargeTable refTable, + List dts + ) { + if (refTable == null) { + addProblem("cannot.find.hist.q.reftable"); + return prepareSimpleData(dts); + } + else { + return prepareData(refTable, dts); + } + } + + + protected WQTimerange[] prepareSimpleData(List dts) { + List wqts = + new ArrayList(values.length); boolean debug = logger.isDebugEnabled(); for (double value: values) { logger.debug("Prepare data for value: " + value); - String name = mode == MODE_W ? "W=" + value : "Q=" + value; + String name = mode == MODE_W ? "W=" + value : "Q=" + value; WQTimerange wqt = null; for (DischargeTable dt: dts) { @@ -184,6 +205,85 @@ } + protected HistoricalWQTimerange[] prepareData( + DischargeTable refTable, + List dts + ) { + List wqts = + new ArrayList(values.length); + + boolean debug = logger.isDebugEnabled(); + + 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; + + if (refTable != null && mode == MODE_W) { + ref = findValueForW(refTable, value); + } + else if (refTable != null) { + ref = findValueForQ(refTable, value); + } + else { + ref = Double.NaN; + } + + for (DischargeTable dt: dts) { + 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(); + } + + Timerange t = new Timerange(ti.getStartTime(),ti.getStopTime()); + double w; + double q; + + if (mode == MODE_W) { + w = value; + q = findValueForW(dt, w); + + if (Double.isNaN(q)) { + logger.warn("Cannot find Q for W: " + w); + addProblem("cannot.find.hist.q.for.w", w, start, end); + continue; + } + } + else { + q = value; + w = findValueForQ(dt, q); + } + + if (debug) { + logger.debug("Q=" + q + " | W=" + w); + } + + if (wqt == null) { + wqt = new HistoricalWQTimerange(name); + } + + wqt.add(w, q, ref-value, t); + } + + if (wqt != null) { + wqts.add(wqt); + } + } + + return (HistoricalWQTimerange[]) + wqts.toArray(new HistoricalWQTimerange[wqts.size()]); + } + + protected double findValueForW(DischargeTable dt, double w) { double[][] vs = DischargeTables.loadDischargeTableValues(dt,SCALE,true); return DischargeTables.getQForW(vs, w); diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/FacetTypes.java Thu Feb 09 10:57:35 2012 +0000 @@ -124,7 +124,8 @@ String REPORT = "report"; - String HISTORICAL_DISCHARGE_Q = "historical_discharge.historicalq"; + String HISTORICAL_DISCHARGE_Q = "historical_discharge.historicalq"; + String HISTORICAL_DISCHARGE_Q_DIFF = "historical_discharge.historicalq.diff"; String REFERENCE_CURVE = "reference_curve"; String REFERENCE_CURVE_NORMALIZED = "reference_curve_normalized"; diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeDifferenceFacet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalDischargeDifferenceFacet.java Thu Feb 09 10:57:35 2012 +0000 @@ -0,0 +1,61 @@ +package de.intevation.flys.artifacts.model; + +import org.apache.log4j.Logger; + +import de.intevation.artifacts.Artifact; +import de.intevation.artifacts.CallContext; + +import de.intevation.flys.artifacts.FLYSArtifact; +import de.intevation.flys.artifacts.states.DefaultState.ComputeType; + + +/** + * @author Ingo Weinzierl + */ +public class HistoricalDischargeDifferenceFacet +extends HistoricalDischargeFacet +{ + private static final Logger logger = + Logger.getLogger(HistoricalDischargeDifferenceFacet.class); + + + public HistoricalDischargeDifferenceFacet( + int index, + String name, + String desc + ) { + super(index, name, desc, ComputeType.ADVANCE, null, null); + } + + + public HistoricalDischargeDifferenceFacet( + int index, + String name, + String description, + ComputeType type, + String stateID, + String hash + + ) { + super(index, name, description, type, hash, stateID); + } + + + @Override + public Object getData(Artifact artifact, CallContext context) { + if (logger.isDebugEnabled()) { + logger.debug("Get data for historical discharge difference curves" + + " at index: " + index + " / stateId: " + stateId); + } + + FLYSArtifact flys = (FLYSArtifact) artifact; + + CalculationResult res = (CalculationResult) + flys.compute(context, hash, stateId, type, false); + + HistoricalWQTimerange[] wqts = (HistoricalWQTimerange[]) res.getData(); + + return wqts[index]; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalWQTimerange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/HistoricalWQTimerange.java Thu Feb 09 10:57:35 2012 +0000 @@ -0,0 +1,49 @@ +package de.intevation.flys.artifacts.model; + +import gnu.trove.TDoubleArrayList; + + +/** + * A subclass of WQTimerange that stores besides W, Q and Timerange values + * another double value. + * + * @author Ingo Weinzierl + */ +public class HistoricalWQTimerange extends WQTimerange { + + protected TDoubleArrayList diffs; + + + public HistoricalWQTimerange(String name) { + super(name); + + diffs = new TDoubleArrayList(); + } + + + public void add(double w, double q, double diff, Timerange t) { + ws.add(w); + qs.add(q); + ts.add(t); + diffs.add(diff); + } + + + /** + * This method requires a 3dim double array for res! + */ + @Override + public double[] get(int idx, double[] res) { + res[0] = ws.getQuick(idx); + res[1] = qs.getQuick(idx); + res[2] = diffs.getQuick(idx); + + return res; + } + + + public double[] getDiffs() { + return diffs.toNativeArray(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTimerange.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTimerange.java Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQTimerange.java Thu Feb 09 10:57:35 2012 +0000 @@ -36,7 +36,7 @@ public Timerange[] getTimeranges() { - return (Timerange[]) ts.toArray(); + return (Timerange[]) ts.toArray(new Timerange[ts.size()]); } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeComputeState.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeComputeState.java Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/HistoricalDischargeComputeState.java Thu Feb 09 10:57:35 2012 +0000 @@ -19,6 +19,8 @@ import de.intevation.flys.artifacts.model.DataFacet; import de.intevation.flys.artifacts.model.FacetTypes; import de.intevation.flys.artifacts.model.HistoricalDischargeFacet; +import de.intevation.flys.artifacts.model.HistoricalDischargeDifferenceFacet; +import de.intevation.flys.artifacts.model.HistoricalWQTimerange; import de.intevation.flys.artifacts.model.ReportFacet; import de.intevation.flys.artifacts.model.WQTimerange; @@ -98,9 +100,20 @@ // TODO CREATE BETTER TITLE FOR FACETS facets.add(new HistoricalDischargeFacet( - i++, + i, HISTORICAL_DISCHARGE_Q, wqt.getName())); + + if (wqt instanceof HistoricalWQTimerange) { + logger.debug("Create another facet for historical differences."); + + facets.add(new HistoricalDischargeDifferenceFacet( + i, + HISTORICAL_DISCHARGE_Q_DIFF, + "DIFF: " + wqt.getName())); + } + + i++; } } } diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveExporter.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveExporter.java Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveExporter.java Thu Feb 09 10:57:35 2012 +0000 @@ -153,7 +153,7 @@ NumberFormat wf = Formatter.getHistoricalDischargeW(context); NumberFormat qf = Formatter.getHistoricalDischargeQ(context); - double[] wq = new double[2]; + double[] wq = new double[3]; String gaugeName = getReferenceGaugename(); @@ -168,7 +168,7 @@ df.format(start) + " - " + df.format(end), wf.format(wq[0]), qf.format(wq[1]), - "TODO: Difference to reference curve", + qf.format(wq[2]), gaugeName }); } diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveGenerator.java --- a/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveGenerator.java Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/HistoricalDischargeCurveGenerator.java Thu Feb 09 10:57:35 2012 +0000 @@ -21,6 +21,7 @@ import de.intevation.flys.artifacts.FLYSArtifact; import de.intevation.flys.artifacts.model.FacetTypes; +import de.intevation.flys.artifacts.model.HistoricalWQTimerange; import de.intevation.flys.artifacts.model.Timerange; import de.intevation.flys.artifacts.model.WQTimerange; import de.intevation.flys.utils.FLYSUtils; @@ -168,6 +169,15 @@ theme, visible); } + else if (name.equals(HISTORICAL_DISCHARGE_Q_DIFF)) { + doHistoricalDischargeDifferenceOut( + (FLYSArtifact) artifactFacet.getArtifact(), + artifactFacet.getData(context), + artifactFacet.getFacetDescription(), + theme, + visible); + } + // TODO ADD THE CASE FOR DISPLAYING W VALUES else { logger.warn("doOut(): unknown facet name: " + name); return; @@ -186,7 +196,30 @@ WQTimerange wqt = (WQTimerange) data; - TimeSeriesCollection tsc = newTimeSeriesCollection(wqt, desc); + TimeSeriesCollection tsc = newTimeSeriesCollection( + wqt.getTimeranges(), + wqt.getQs(), + desc); + + addAxisDataset(tsc, 0, visible); + } + + + protected void doHistoricalDischargeDifferenceOut( + FLYSArtifact artifact, + Object data, + String desc, + Document theme, + boolean visible + ) { + logger.debug("doHistoricalDischargeDifferenceOut: desc = " + desc); + + HistoricalWQTimerange wqt = (HistoricalWQTimerange) data; + + TimeSeriesCollection tsc = newTimeSeriesCollection( + wqt.getTimeranges(), + wqt.getDiffs(), + desc); addAxisDataset(tsc, 0, visible); } @@ -199,7 +232,8 @@ * looks like a "step chart". */ protected TimeSeriesCollection newTimeSeriesCollection( - WQTimerange wqt, + Timerange[] timeranges, + double[] values, String desc ) { logger.debug("Create new TimeSeriesCollection for: " + desc); @@ -207,30 +241,22 @@ TimeSeriesCollection tsc = new TimeSeriesCollection(); TimeSeries series = new TimeSeries(desc); - Timerange tr = null; - double[] res = new double[2]; - - for (int i = 0, n = wqt.size(); i < n; i++) { - res = wqt.get(i, res); - - RegularTimePeriod[] rtp = newRegularTimePeriod(wqt.getTimerange(i)); + for (int i = 0, n = timeranges.length; i < n; i++) { + RegularTimePeriod[] rtp = newRegularTimePeriod(timeranges[i]); try { - // TODO WHICH (W/Q) IS REQUIRED? - double y = res[1]; - - if (Double.isNaN(y)) { + if (Double.isNaN(values[i])) { logger.warn("Skip TimePeriod because value is NaN."); continue; } - series.add(rtp[0], y); - series.add(rtp[1], y); + series.add(rtp[0], values[i]); + series.add(rtp[1], values[i]); if (logger.isDebugEnabled()) { logger.debug("added Item to TimeSeries:"); logger.debug(" TimePeriod: " + rtp[0] + " - " + rtp[1]); - logger.debug(" Value: " + res[1]); + logger.debug(" Value: " + values[i]); } } catch (SeriesException se) { diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/resources/messages.properties --- a/flys-artifacts/src/main/resources/messages.properties Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages.properties Thu Feb 09 10:57:35 2012 +0000 @@ -181,6 +181,7 @@ relating.w.w.failed = Relating W with W failed. cannot.find.hist.q.for.w = Cannot find Q for W = {0,number,#.##} in timerange {1, date} - {2, date} cannot.find.hist.q.tables = Cannot find Discharge Tables for given timerange. +cannot.find.hist.q.reftable = Cannot find reference Discharge Table for specified Gauge. no.river.selected = No river selected. no.gauge.selected = No gauge selected. diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/resources/messages_de.properties --- a/flys-artifacts/src/main/resources/messages_de.properties Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_de.properties Thu Feb 09 10:57:35 2012 +0000 @@ -181,6 +181,7 @@ relating.w.w.failed = W-zu-W-Zuordnung fehlgeschlagen. cannot.find.hist.q.for.w = Konnte zu W = {0,number,#.##} im Zeitraum ({1,date} - {2,date}) kein Abfluss ermitteln. cannot.find.hist.q.tables = Konnte f\u00fcr den angegebenen Zeitraum keine Abflusstafeln finden. +cannot.find.hist.q.reftable = Konnte f\u00fcr den gew\u00e4hlten Pegel keine Bezugs-Abflusstafel ermitteln. no.river.selected = Kein Gew\u00e4sser ausgew\u00e4hlt. no.gauge.selected = Kein Pegel ausgew\u00e4hlt. diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/resources/messages_de_DE.properties --- a/flys-artifacts/src/main/resources/messages_de_DE.properties Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_de_DE.properties Thu Feb 09 10:57:35 2012 +0000 @@ -181,6 +181,7 @@ relating.w.w.failed = W-zu-W-Zuordnung fehlgeschlagen. cannot.find.hist.q.for.w = Konnte zu W = {0,number,#.##} im Zeitraum ({1,date} - {2,date}) kein Abfluss ermitteln. cannot.find.hist.q.tables = Konnte f\u00fcr den angegebenen Zeitraum keine Abflusstafeln finden. +cannot.find.hist.q.reftable = Konnte f\u00fcr den gew\u00e4hlten Pegel keine Bezugs-Abflusstafel ermitteln. no.river.selected = Kein Gew\u00e4sser ausgew\u00e4hlt. no.gauge.selected = Kein Pegel ausgew\u00e4hlt. diff -r ecb76933362f -r b8df8d1476ba flys-artifacts/src/main/resources/messages_en.properties --- a/flys-artifacts/src/main/resources/messages_en.properties Thu Feb 09 10:21:16 2012 +0000 +++ b/flys-artifacts/src/main/resources/messages_en.properties Thu Feb 09 10:57:35 2012 +0000 @@ -177,6 +177,7 @@ relating.w.w.failed = Relating W with W failed. cannot.find.hist.q.for.w = Cannot find Q for W = {0,number,#.##} in timerange {1, date} - {2, date} cannot.find.hist.q.tables = Cannot find Discharge Tables for given timerange. +cannot.find.hist.q.reftable = Cannot find reference Discharge Table for specified Gauge. no.river.selected = No river selected. no.gauge.selected = No gauge selected.