# HG changeset patch # User Ingo Weinzierl # Date 1304424332 0 # Node ID 478940d068764d2d075f906a153a99c2fd513e5d # Parent 88614ddfc1e3978f9829c01010532f1e0635eeed Enabled the WINFO artifact to create duration curves - new OutGenerator, added methods for data computation. flys-artifacts/trunk@1802 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/ChangeLog --- a/flys-artifacts/ChangeLog Tue May 03 09:23:17 2011 +0000 +++ b/flys-artifacts/ChangeLog Tue May 03 12:05:32 2011 +0000 @@ -1,3 +1,26 @@ +2011-05-03 Ingo Weinzierl + + * src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java: + New. An OutGenerator for creating duration curves. + + * src/main/java/de/intevation/flys/artifacts/model/WQDay.java: New. A + model class to store necessary data for creating W and Q facets of a + duration curve. This model stores W, Q and Days. + + * src/main/java/de/intevation/flys/artifacts/model/MainValuesFactory.java: + Added a function to retrieve tuples of (day, q) based on a given gauge - + these tuples are necessary for creating duration curves. + + * src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java: Added + methods to compute and retrieve the data necessary for creating duration + curves. + + * src/main/java/de/intevation/flys/artifacts/states/LocationSelect.java: + Bugfix: improved the access to the location array (avoid + NullPointerException). + + * doc/conf/conf.xml: Registered the new OutGenerator for duration curves. + 2011-05-03 Sascha L. Teichmann * contrib/visualize-transitions.xsl: State quoting was done wrong. diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/doc/conf/conf.xml --- a/flys-artifacts/doc/conf/conf.xml Tue May 03 09:23:17 2011 +0000 +++ b/flys-artifacts/doc/conf/conf.xml Tue May 03 12:05:32 2011 +0000 @@ -51,6 +51,7 @@ de.intevation.flys.exports.DischargeCurveGenerator de.intevation.flys.exports.LongitudinalSectionGenerator + de.intevation.flys.exports.DurationCurveGenerator diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java Tue May 03 09:23:17 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java Tue May 03 12:05:32 2011 +0000 @@ -20,10 +20,13 @@ import de.intevation.artifacts.common.utils.XMLUtils; +import de.intevation.flys.model.Gauge; import de.intevation.flys.model.River; import de.intevation.flys.artifacts.states.DefaultState; import de.intevation.flys.artifacts.context.FLYSContext; +import de.intevation.flys.artifacts.model.MainValuesFactory; +import de.intevation.flys.artifacts.model.WQDay; import de.intevation.flys.artifacts.model.WQKms; import de.intevation.flys.artifacts.model.WstValueTable; @@ -301,5 +304,77 @@ return wqkms; } + + + /** + * Returns the data that is computed by a duration curve computation. + * + * @return the data computed by a duration curve computation. + */ + public WQDay getDurationCurveData() + throws NullPointerException + { + logger.debug("WINFOArtifact.getDurationCurveData"); + + River r = getRiver(); + + if (r == null) { + throw new NullPointerException("Cannot determine river."); + } + + Gauge g = getGauge(); + + if (g == null) { + throw new NullPointerException("Cannot determine gauge."); + } + + double[] locations = getLocations(); + + if (locations == null) { + throw new NullPointerException("Cannot determine location."); + } + + WstValueTable wst = WstValueTable.getTable(r); + if (wst == null) { + throw new NullPointerException("No Wst found for selected river."); + } + + // TODO Introduce a caching mechanism here! + + return computeDurationCurveData(g, wst, locations[0]); + } + + + /** + * Computes the data used to create duration curves. + * + * @param gauge The selected gauge. + * @param location The selected location. + * + * @return the computed data. + */ + public static WQDay computeDurationCurveData( + Gauge gauge, + WstValueTable wst, + double location) + { + logger.info("WINFOArtifact.computeDurationCurveData"); + + Object[] obj = MainValuesFactory.getDurationCurveData(gauge); + + int[] days = (int[]) obj[0]; + double[] qs = (double[]) obj[1]; + + double[] interpolatedW = new double[qs.length]; + interpolatedW = wst.interpolateW(location, qs, interpolatedW); + + WQDay wqday = new WQDay(qs.length); + + for (int i = 0; i < days.length; i++) { + wqday.add(days[i], interpolatedW[i], qs[i]); + } + + return wqday; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesFactory.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesFactory.java Tue May 03 09:23:17 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/MainValuesFactory.java Tue May 03 12:05:32 2011 +0000 @@ -1,7 +1,10 @@ package de.intevation.flys.artifacts.model; +import java.math.BigDecimal; import java.util.List; +import org.apache.log4j.Logger; + import org.hibernate.Session; import org.hibernate.Query; @@ -16,6 +19,8 @@ */ public class MainValuesFactory { + private static Logger logger = Logger.getLogger(MainValuesFactory.class); + public static List getMainValues(Gauge gauge) { Session session = SessionHolder.HOLDER.get(); @@ -25,5 +30,51 @@ return query.list(); } + + + /** + * Returns an array of [days, qs] necessary to create duration curves. + * + * @param gauge The selected gauge. + * + * @return a 2dim array of [days, qs] where days is an int[] and qs is + * an double[]. + */ + public static Object[] getDurationCurveData(Gauge gauge) { + Session session = SessionHolder.HOLDER.get(); + + Query query = session.createQuery( + "select cast(nmv.name as integer) as days, mv.value as q " + + "from MainValue as mv " + + "join mv.mainValue as nmv " + + "join nmv.type mvt " + + "where mvt.name = 'D' and mv.gauge.id = :gauge_id " + + "order by days"); + + query.setParameter("gauge_id", gauge.getId()); + + List results = query.list(); + int[] days = new int[results.size()]; + double[] qs = new double[results.size()]; + + int idx = 0; + + for (Object obj: results) { + Object[] arr = (Object[]) obj; + + try { + int day = ((Integer) arr[0]).intValue(); + double q = ((BigDecimal) arr[1]).doubleValue(); + + days[idx] = day; + qs[idx++] = q; + } + catch (NumberFormatException nfe) { + logger.warn(nfe, nfe); + } + } + + return new Object[] { days, qs }; + } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 : diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQDay.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/WQDay.java Tue May 03 12:05:32 2011 +0000 @@ -0,0 +1,64 @@ +package de.intevation.flys.artifacts.model; + +import java.io.Serializable; + +import gnu.trove.TDoubleArrayList; +import gnu.trove.TIntArrayList; + + +/** + * This class represents a pool of data triples that consists of 'W', 'Q' and + * 'Day' data. + * + * @author Ingo Weinzierl + */ +public class WQDay implements Serializable { + + protected TIntArrayList days; + + protected TDoubleArrayList ws; + + protected TDoubleArrayList qs; + + + public WQDay() { + days = new TIntArrayList(); + ws = new TDoubleArrayList(); + qs = new TDoubleArrayList(); + } + + + public WQDay(int capacity) { + days = new TIntArrayList(capacity); + ws = new TDoubleArrayList(capacity); + qs = new TDoubleArrayList(capacity); + } + + + public void add(int day, double w, double q) { + days.add(day); + ws.add(w); + qs.add(q); + } + + + public int size() { + return days.size(); + } + + + public int getDay(int idx) { + return days.get(idx); + } + + + public double getW(int idx) { + return ws.get(idx); + } + + + public double getQ(int idx) { + return qs.get(idx); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationSelect.java --- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationSelect.java Tue May 03 09:23:17 2011 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/states/LocationSelect.java Tue May 03 12:05:32 2011 +0000 @@ -60,7 +60,7 @@ logger.debug("Inserted min location: " + mm[0]); logger.debug("Inserted max location: " + mm[mm.length-1]); - return validateBounds(minmax[0], minmax[1], mm[0], mm[1], 0d); + return validateBounds(minmax[0], minmax[1], mm[0], mm[mm.length-1], 0d); } diff -r 88614ddfc1e3 -r 478940d06876 flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flys-artifacts/src/main/java/de/intevation/flys/exports/DurationCurveGenerator.java Tue May 03 12:05:32 2011 +0000 @@ -0,0 +1,166 @@ +package de.intevation.flys.exports; + +import org.w3c.dom.Document; + +import org.apache.log4j.Logger; + +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.plot.XYPlot; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; + +import de.intevation.artifacts.Artifact; + +import de.intevation.flys.artifacts.WINFOArtifact; +import de.intevation.flys.artifacts.model.WQDay; + + +/** + * An OutGenerator that generates duration curves. + * + * @author Ingo Weinzierl + */ +public class DurationCurveGenerator extends XYChartGenerator { + + private static Logger logger = + Logger.getLogger(DurationCurveGenerator.class); + + /** The storage for the W series to be drawn in this chart.*/ + protected XYSeriesCollection w; + + /** The storage for the Q series to be drawn in this chart.*/ + protected XYSeriesCollection q; + + + public static final String DURATION_CURVE_W = + "duration_curve.w"; + + public static final String DURATION_CURVE_Q = + "duration_curve.q"; + + + public DurationCurveGenerator() { + super(); + + this.w = new XYSeriesCollection(); + this.q = new XYSeriesCollection(); + } + + + protected String getChartTitle() { + // TODO i18n + return "Wasserstand für Gewässer"; + } + + + protected String getXAxisLabel() { + // TODO i18n + return "Unterschreitungsdauer [Tagen]"; + } + + + protected String getYAxisLabel() { + return "W [NN + m]"; + } + + + public void addDatasets(JFreeChart chart) { + XYPlot plot = (XYPlot) chart.getPlot(); + + plot.setDataset(0, w); + plot.setDataset(1, q); + } + + + protected void adjustAxes(XYPlot plot) { + super.adjustAxes(plot); + + NumberAxis qAxis = new NumberAxis("Q [m³/s]"); + + plot.setRangeAxis(2, qAxis); + plot.mapDatasetToRangeAxis(1, 2); + } + + + public void doOut(Artifact artifact, String facet, Document attr) { + logger.debug("DurationCurveGenerator.doOut: " + facet); + + if (facet == null || facet.length() == 0) { + logger.error("No facet given. Cannot create dataset."); + return; + } + + if (facet.equals(DURATION_CURVE_W)) { + doWOut(getDurationCurveData(artifact)); + } + else if (facet.equals(DURATION_CURVE_Q)) { + doQOut(getDurationCurveData(artifact)); + } + else { + logger.warn("Unknown facet name: " + facet); + return; + } + } + + + /** + * Creates the series for a duration curve's W facet. + * + * @param wqdays The WQDay store that contains the Ws. + */ + protected void doWOut(WQDay wqdays) { + logger.debug("DurationCurveGenerator.doWOut"); + + // TODO find the correct series name + XYSeries series = new XYSeries("W-1"); + + int size = wqdays.size(); + for (int i = 0; i < size; i++) { + int day = wqdays.getDay(i); + double w = wqdays.getW(i); + + series.add((double) day, w); + } + + this.w.addSeries(series); + } + + + /** + * Creates the series for a duration curve's Q facet. + * + * @param wqdays The WQDay store that contains the Qs. + */ + protected void doQOut(WQDay wqdays) { + logger.debug("DurationCurveGenerator.doQOut"); + + // TODO find the correct series name + XYSeries series = new XYSeries("Q-1"); + + int size = wqdays.size(); + for (int i = 0; i < size; i++) { + int day = wqdays.getDay(i); + double q = wqdays.getQ(i); + + series.add((double) day, q); + } + + this.q.addSeries(series); + } + + + /** + * Returns the computed data for a duration curve based on the artifact's + * computation method. + * + * @param artifact The WINFO artifact. + * + * @return the computed data for a duration curve's W and Q facet. + */ + protected WQDay getDurationCurveData(Artifact artifact) { + WINFOArtifact winfoArtifact = (WINFOArtifact) artifact; + return winfoArtifact.getDurationCurveData(); + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :