changeset 8206:436512d9bd94

Added processor for discharge curve in fixanalysis.
author Raimund Renkert <rrenkert@intevation.de>
date Fri, 05 Sep 2014 15:57:39 +0200 (2014-09-05)
parents 04d1d56d896b
children de280599dd2f
files artifacts/doc/conf/generators/discharge-diagram-defaults.xml artifacts/src/main/java/org/dive4elements/river/exports/process/FixWQProcessor.java
diffstat 2 files changed, 532 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/generators/discharge-diagram-defaults.xml	Fri Sep 05 15:26:40 2014 +0200
+++ b/artifacts/doc/conf/generators/discharge-diagram-defaults.xml	Fri Sep 05 15:57:39 2014 +0200
@@ -10,4 +10,5 @@
     <processor class="org.dive4elements.river.exports.process.MiscDischargeProcessor" axis="W"/>
     <processor class="org.dive4elements.river.exports.process.ComputedDischargeProcessor" axis="W"/>
     <processor class="org.dive4elements.river.exports.process.HistoricalDischargeProcessor" axis="W"/>
+    <processor class="org.dive4elements.river.exports.process.FixWQProcessor" axis="W"/>
 </discharge-defaults>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/process/FixWQProcessor.java	Fri Sep 05 15:57:39 2014 +0200
@@ -0,0 +1,531 @@
+package org.dive4elements.river.exports.process;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
+import org.dive4elements.river.artifacts.model.FacetTypes;
+import org.dive4elements.river.artifacts.model.NamedDouble;
+import org.dive4elements.river.artifacts.model.QWDDateRange;
+import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.model.fixings.FixFunction;
+import org.dive4elements.river.artifacts.model.fixings.FixWQCurveFacet;
+import org.dive4elements.river.artifacts.model.fixings.QWD;
+import org.dive4elements.river.artifacts.model.fixings.QWI;
+import org.dive4elements.river.exports.DiagramGenerator;
+import org.dive4elements.river.exports.StyledSeriesBuilder;
+import org.dive4elements.river.exports.fixings.FixChartGenerator;
+import org.dive4elements.river.exports.fixings.FixWQCurveGenerator;
+import org.dive4elements.river.java2d.ShapeUtils;
+import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation;
+import org.dive4elements.river.jfree.JFreeUtil;
+import org.dive4elements.river.jfree.RiverAnnotation;
+import org.dive4elements.river.jfree.StickyAxisAnnotation;
+import org.dive4elements.river.jfree.StyledXYSeries;
+import org.dive4elements.river.themes.ThemeDocument;
+import org.jfree.chart.annotations.XYTextAnnotation;
+import org.jfree.chart.plot.Marker;
+import org.jfree.chart.plot.ValueMarker;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.ui.RectangleAnchor;
+import org.jfree.ui.RectangleInsets;
+import org.jfree.ui.TextAnchor;
+
+
+public class FixWQProcessor
+extends DefaultProcessor
+implements FacetTypes
+{
+
+    private static Logger logger = Logger.getLogger(FixWQProcessor.class);
+
+    public FixWQProcessor() {
+    }
+
+    @Override
+    public void doOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        boolean visible
+    ) {
+        // TODO: Simplyfy this processor and move general facets/data to 
+        // MiscDischargeProcessor or something...
+        String facetType = bundle.getFacetName();
+        logger.debug("facet: " + facetType + " name: " + bundle.getFacetDescription());
+        if(facetType.startsWith(FIX_SECTOR_AVERAGE_WQ)) {
+            doSectorAverageOut(generator, bundle, theme, visible);
+        }
+        else if(FIX_ANALYSIS_EVENTS_WQ.equals(facetType)
+            || FIX_REFERENCE_EVENTS_WQ.equals(facetType)
+            || FIX_EVENTS.equals(facetType)) {
+            doEventsOut(generator, bundle, theme, visible);
+        }
+        else if(FIX_WQ_CURVE.equals(facetType)) {
+            doWQCurveOut(generator, bundle, theme, visible);
+        }
+        else if(FIX_OUTLIER.equals(facetType)) {
+            doOutlierOut(generator, bundle, theme, visible);
+        }
+        else if(QSECTOR.equals(facetType)) {
+            doQSectorOut(generator, bundle, theme, visible);
+        }
+        else if(STATIC_WKMS_MARKS.equals(facetType) ||
+                STATIC_WKMS.equals(facetType) ||
+                HEIGHTMARKS_POINTS.equals(facetType) ) {
+            doWAnnotations(generator, bundle, theme, visible);
+        }
+        else if (LONGITUDINAL_W.equals(facetType)
+            || STATIC_WKMS_INTERPOL.equals(facetType)
+            || FIX_WQ_LS.equals(facetType)) {
+            doWQOut(generator, bundle, theme, visible);
+        }
+    }
+
+    /** Add sector average points to chart. */
+    protected void doSectorAverageOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        boolean visible
+    ) {
+        logger.debug("doSectorAverageOut");
+        QWDDateRange qwdd = (QWDDateRange)bundle.getData(generator.getCallContext());
+        QWD qwd = qwdd != null ? qwdd.getQWD() : null;
+
+        if(qwd != null) {
+            XYSeries series = new StyledXYSeries(
+                bundle.getFacetDescription(),
+                false, true,
+                theme);
+            DateFormat dateFormat = DateFormat.getDateInstance(
+                DateFormat.SHORT);
+
+            //TODO: W in cm at Gauge!!!
+            series.add(qwd.getQ(), qwd.getW(), false);
+
+            XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
+                    dateFormat.format(qwd.getDate()),
+                    qwd.getQ(),
+                    qwd.getW());
+            List<XYTextAnnotation> annos = new ArrayList<XYTextAnnotation>();
+            annos.add(anno);
+            generator.addAxisSeries(series, axisName, visible);
+
+            if (visible && theme != null && theme.parseShowPointLabel()) {
+                RiverAnnotation flysAnno =
+                        new RiverAnnotation(null, null, null, theme);
+                flysAnno.setTextAnnotations(annos);
+                generator.addAnnotations(flysAnno);
+            }
+        }
+        else {
+            logger.debug("doSectorAverageOut: qwd == null");
+        }
+    }
+
+
+    /** Add analysis event points to chart. */
+    protected void doEventsOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument    theme,
+        boolean          visible
+    ) {
+        logger.debug("doAnalysisEventsOut");
+
+        QWD qwd = (QWD)bundle.getData(generator.getCallContext());
+
+        if (qwd == null) {
+            logger.debug("doAnalysisEventsOut: qwd == null");
+            return;
+        }
+// TODO: W in cm at Gauge!!!
+        //double gaugeDatum = getCurrentGaugeDatum();
+        //boolean atGauge = gaugeDatum != 0d;
+
+        //double factor = atGauge ? 100d : 1d;
+
+        //double w = factor*(qwd.getW()-gaugeDatum);
+
+        // Force empty symbol.
+        if (qwd.getInterpolated()) {
+            theme = new ThemeDocument(theme); // prevent potential side effects.
+            theme.setValue(ThemeDocument.USE_FILL_PAINT, "true");
+        }
+
+        XYSeries series = new StyledXYSeries(
+            bundle.getFacetDescription(),
+            theme,
+            qwd.getInterpolated()
+                ? ShapeUtils.INTERPOLATED_SHAPE
+                : ShapeUtils.MEASURED_SHAPE);
+
+        series.add(qwd.getQ(), qwd.getW());
+
+        generator.addAxisSeries(series, axisName, visible);
+
+        if (visible && theme.parseShowPointLabel()) {
+
+            List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
+
+            DateFormat dateFormat = DateFormat.getDateInstance(
+                DateFormat.SHORT);
+            XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
+                dateFormat.format(qwd.getDate()),
+                qwd.getQ(),
+                qwd.getW());
+            textAnnos.add(anno);
+
+            RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme);
+            flysAnno.setTextAnnotations(textAnnos);
+            generator.addAnnotations(flysAnno);
+        }
+    }
+
+    /** Add reference event points to chart. */
+    protected void doReferenceEventsOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        boolean visible) {
+        logger.debug("doReferenceEventsOut");
+
+        QWI qwd = (QWI)bundle.getData(generator.getCallContext());
+        if (qwd == null) {
+            logger.debug("doReferenceEventsOut: qwds == null in " + bundle.getFacetDescription());
+            return;
+        }
+
+        // Force empty symbol.
+        if (qwd.getInterpolated()) {
+            theme = new ThemeDocument(theme); // prevent potential side effects.
+            theme.setValue(ThemeDocument.USE_FILL_PAINT, "true");
+        }
+
+        XYSeries series = new StyledXYSeries(
+            bundle.getFacetDescription(),
+            false, true, theme,
+            qwd.getInterpolated()
+                ? ShapeUtils.INTERPOLATED_SHAPE
+                : ShapeUtils.MEASURED_SHAPE);
+
+// TODO: W in cm at gauge!!!
+        //double gaugeDatum = getCurrentGaugeDatum();
+        //boolean atGauge = gaugeDatum != 0d;
+
+        //double factor = atGauge ? 100d : 1d;
+        //double w = factor*(qwd.getW()-gaugeDatum);
+
+        series.add(qwd.getQ(), qwd.getW(), false);
+
+        if (visible && theme.parseShowPointLabel()) {
+            DateFormat dateFormat = DateFormat.getDateInstance(
+                DateFormat.SHORT);
+
+            XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
+                dateFormat.format(qwd.getDate()),
+                qwd.getQ(),
+                qwd.getW());
+
+            List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
+            textAnnos.add(anno);
+            RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme);
+            flysAnno.setTextAnnotations(textAnnos);
+            generator.addAnnotations(flysAnno);
+        }
+
+        generator.addAxisSeries(series, axisName, visible);
+    }
+
+    protected void doWQCurveOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        boolean visible
+    ) {
+        logger.debug("doWQCurveOut");
+
+        FixWQCurveFacet facet = (FixWQCurveFacet)bundle.getFacet();
+        FixFunction func = (FixFunction)facet.getData(
+                bundle.getArtifact(), generator.getCallContext());
+
+        if (func == null) {
+            logger.warn("doWQCurveOut: Facet does not contain FixFunction");
+            return;
+        }
+
+        double maxQ = func.getMaxQ();
+
+        if (maxQ > 0) {
+            StyledXYSeries series = JFreeUtil.sampleFunction2D(
+                    func.getFunction(),
+                    theme,
+                    bundle.getFacetDescription(),
+                    500,   // number of samples
+                    0.0 ,  // start
+                    maxQ); // end
+
+            //TODO: W in cm at gauge!!!
+//            double gaugeDatum = getCurrentGaugeDatum();
+
+//            if (gaugeDatum == 0d) {
+                generator.addAxisSeries(series, axisName, visible);
+//            }
+/*            else {
+                StyledXYSeries series2 = JFreeUtil.sampleFunction2D(
+                        func.getFunction(),
+                        doc,
+                        aaf.getFacetDescription(),
+                        500,   // number of samples
+                        0.0 ,  // start
+                        maxQ); // end
+                addAxisSeries(series2, YAXIS.W.idx, false);
+                // Use second axis at cm if at gauge.
+                for (int i = 0, N = series.getItemCount(); i < N; i++) {
+                    series.updateByIndex(
+                        i, new Double(100d*(series.getY(i).doubleValue()-gaugeDatum)));
+                }
+                addAxisSeries(series, YAXIS.WCm.idx, visible);
+            }*/
+        }
+        else {
+            logger.warn("doWQCurveOut: maxQ <= 0");
+        }
+    }
+
+    protected void doOutlierOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        boolean visible
+    ) {
+        logger.debug("doOutlierOut");
+
+        QWI[] qws = (QWI[])bundle.getData(generator.getCallContext());
+        if(qws != null) {
+            XYSeries series = new StyledXYSeries(
+                bundle.getFacetDescription(),
+                false, true,
+                theme);
+            DateFormat dateFormat = DateFormat.getDateInstance(
+                DateFormat.SHORT);
+
+            List<XYTextAnnotation> annos = new ArrayList<XYTextAnnotation>();
+            //TODO: W in cm at Gauge!!!
+            for (QWI qw: qws) {
+                series.add(qw.getQ(), qw.getW(), false);
+
+                XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
+                        dateFormat.format(qw.getDate()),
+                        qw.getQ(),
+                        qw.getW());
+                annos.add(anno);
+            }
+            generator.addAxisSeries(series, axisName, visible);
+
+            if (visible && theme != null && theme.parseShowPointLabel()) {
+                RiverAnnotation flysAnno =
+                        new RiverAnnotation(null, null, null, theme);
+                flysAnno.setTextAnnotations(annos);
+                generator.addAnnotations(flysAnno);
+            }
+        }
+        else {
+            logger.debug("doOutlierOut: qwd == null");
+        }
+    }
+
+    /** Add markers for q sectors. */
+    protected void doQSectorOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument theme,
+        boolean visible
+    ) {
+        logger.debug("doQSectorOut");
+        if (!visible) {
+            return;
+        }
+
+        Object qsectorsObj = bundle.getData(generator.getCallContext());
+        if (qsectorsObj == null || !(qsectorsObj instanceof List)) {
+            logger.warn("No QSectors coming from data.");
+            return;
+        }
+
+        List<?> qsectorsList = (List<?>) qsectorsObj;
+        if (qsectorsList.size() == 0 || !(qsectorsList.get(0) instanceof NamedDouble)) {
+            logger.warn("No QSectors coming from data.");
+            return;
+        }
+
+        @SuppressWarnings("unchecked")
+        List<NamedDouble> qsectors = (List<NamedDouble>) qsectorsList;
+
+        for (NamedDouble qsector : qsectors) {
+            if (Double.isNaN(qsector.getValue())) {
+                continue;
+            }
+            Marker m = new ValueMarker(qsector.getValue());
+            m.setPaint(Color.black);
+
+            float[] dashes = theme.parseLineStyle();
+            int size       = theme.parseLineWidth();
+            BasicStroke stroke;
+            if (dashes.length <= 1) {
+                stroke = new BasicStroke(size);
+            }
+            else {
+                stroke = new BasicStroke(size,
+                        BasicStroke.CAP_BUTT,
+                        BasicStroke.JOIN_ROUND,
+                        1.0f,
+                        dashes,
+                        0.0f);
+            }
+            m.setStroke(stroke);
+
+            if (theme.parseShowLineLabel()) {
+                m.setLabel(qsector.getName());
+                m.setPaint(theme.parseTextColor());
+                m.setLabelFont(theme.parseTextFont());
+            }
+            Color paint = theme.parseLineColorField();
+            if (paint != null) {
+                m.setPaint(paint);
+            }
+            m.setLabelAnchor(RectangleAnchor.TOP_LEFT);
+            m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
+            m.setLabelOffset(new RectangleInsets(5, 5, 10, 10));
+            generator.addDomainMarker(m);
+        }
+    }
+
+    /**
+     * Add W-Annotations to plot.
+     * @param wqkms actual data (double[][]).
+     * @param theme theme to use.
+     */
+    protected void doWAnnotations(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument    theme,
+        boolean          visible
+    ) {
+        Object data = bundle.getData(generator.getCallContext());
+        List<StickyAxisAnnotation> xy = new ArrayList<StickyAxisAnnotation>();
+        if (data instanceof double[][]) {
+            logger.debug("Got double[][]");
+            double [][] values = (double [][]) data;
+            for (int i = 0; i< values[0].length; i++) {
+                xy.add(new StickyAxisAnnotation(bundle.getFacetDescription(),
+                        (float) values[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS));
+            }
+
+            if (visible) {
+                generator.addAnnotations(
+                    new RiverAnnotation(
+                        bundle.getFacetDescription(), xy, null, theme));
+            }
+        }
+        else {
+            // Assume its WKms.
+            logger.debug("Got WKms");
+            /* TODO
+            WKms wkms = (WKms) data;
+
+            Double ckm =
+                (Double) generator.getCallContext().getContextValue(FixChartGenerator.CURRENT_KM);
+            double location = (ckm != null)
+                    ? ckm.doubleValue()
+                    : getRange()[0];
+            double w = StaticWKmsArtifact.getWAtKmLin(data, location);
+            xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(),
+                    (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS));
+
+            doAnnotations(new RiverAnnotation(facet.getDescription(), xy),
+                    aandf, theme, visible);*/
+        }
+    }
+
+    /**
+     * Add WQ Data to plot.
+     * @param wqkms data as double[][]
+     */
+    protected void doWQOut(
+        DiagramGenerator generator,
+        ArtifactAndFacet bundle,
+        ThemeDocument    theme,
+        boolean          visible
+    ) {
+        logger.debug("FixWQCurveGenerator: doWQOut");
+        Object data = bundle.getData(generator.getCallContext());
+        if (data instanceof WQKms) {
+            WQKms wqkms = (WQKms)data;
+            // TODO As in doEventsOut, the value-searching should
+            // be delivered by the facet already (instead of in the Generator).
+            logger.debug("FixWQCurveGenerator: doWQOut: WQKms");
+            XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), theme);
+            // TODO: Remove dependency to FixChartGenerator. 
+            Double ckm = (Double) generator.getCallContext().getContextValue(FixChartGenerator.CURRENT_KM);
+            if (wqkms == null || wqkms.getKms().length == 0 || ckm == null) {
+                logger.info("addPointFromWQKms: No event data to show.");
+                return;
+            }
+            double[] kms = wqkms.getKms();
+            // TODO W in cm at gauge!!!
+            //double gaugeDatum = getCurrentGaugeDatum();
+            //double factor = (gaugeDatum == 0d) ? 1d : 100d;
+            for (int i = 0 ; i< kms.length; i++) {
+                // TODO: Remove dependency to FixWQCurveGenerator.
+                if (Math.abs(kms[i] - ckm) <= FixWQCurveGenerator.EPSILON) {
+                    series.add(wqkms.getQ(i), wqkms.getW(i), false);
+                    generator.addAxisSeries(series, axisName, visible);
+                    if(visible && theme.parseShowPointLabel()) {
+                        List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();
+                        XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
+                            bundle.getFacetDescription(),
+                            wqkms.getQ(i),
+                            wqkms.getW(i));
+                        textAnnos.add(anno);
+                        RiverAnnotation flysAnno = new RiverAnnotation(null, null, null, theme);
+                        flysAnno.setTextAnnotations(textAnnos);
+                        generator.addAnnotations(flysAnno);
+                    }
+                    return;
+                }
+            }
+        }
+        else {
+            logger.debug("FixWQCurveGenerator: doWQOut: double[][]");
+            double [][] values = (double [][]) data;
+
+            XYSeries series = new StyledXYSeries(bundle.getFacetDescription(), false, true, theme);
+            StyledSeriesBuilder.addPoints(series, values, true);
+
+            generator.addAxisSeries(series, axisName, visible);
+        }
+    }
+
+    @Override
+    public boolean canHandle(String facettype) {
+        return facettype.startsWith(FIX_SECTOR_AVERAGE_WQ)
+            || FIX_ANALYSIS_EVENTS_WQ.equals(facettype)
+            || FIX_REFERENCE_EVENTS_WQ.equals(facettype)
+            || FIX_EVENTS.equals(facettype)
+            || FIX_WQ_CURVE.equals(facettype)
+            || FIX_OUTLIER.equals(facettype)
+            || QSECTOR.equals(facettype)
+            || STATIC_WKMS_MARKS.equals(facettype)
+            || STATIC_WKMS.equals(facettype)
+            || HEIGHTMARKS_POINTS.equals(facettype)
+            || LONGITUDINAL_W.equals(facettype)
+            || STATIC_WKMS_INTERPOL.equals(facettype)
+            || FIX_WQ_LS.equals(facettype);
+    }
+}

http://dive4elements.wald.intevation.org