view flys-artifacts/src/main/java/de/intevation/flys/exports/fixings/FixWQCurveGenerator.java @ 3596:6aea625190da

Handle former W calculations in fixA W/Q out. flys-artifacts/trunk@5218 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Felix Wolfsteller <felix.wolfsteller@intevation.de>
date Thu, 16 Aug 2012 09:49:21 +0000
parents 0ac28739ee15
children 66f539df4e8b
line wrap: on
line source
package de.intevation.flys.exports.fixings;

import de.intevation.artifactdatabase.state.ArtifactAndFacet;
import de.intevation.artifactdatabase.state.Facet;
import de.intevation.flys.artifacts.FLYSArtifact;
import de.intevation.flys.artifacts.StaticWKmsArtifact;
import de.intevation.flys.artifacts.WINFOArtifact;
import de.intevation.flys.artifacts.access.FixAnalysisAccess;
import de.intevation.flys.artifacts.model.DateRange;
import de.intevation.flys.artifacts.model.FacetTypes;
import de.intevation.flys.artifacts.model.NamedDouble;
import de.intevation.flys.artifacts.model.QWDDateRange;
import de.intevation.flys.artifacts.model.WKms;
import de.intevation.flys.artifacts.model.WQKms;
import de.intevation.flys.artifacts.model.fixings.FixFunction;
import de.intevation.flys.artifacts.model.fixings.FixWQCurveFacet;
import de.intevation.flys.artifacts.model.fixings.QW;
import de.intevation.flys.artifacts.model.fixings.QWD;
import de.intevation.flys.artifacts.resources.Resources;
import de.intevation.flys.exports.ChartGenerator;
import de.intevation.flys.exports.StyledSeriesBuilder;
import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation;
import de.intevation.flys.jfree.FLYSAnnotation;
import de.intevation.flys.jfree.JFreeUtil;
import de.intevation.flys.jfree.StickyAxisAnnotation;
import de.intevation.flys.jfree.StyledXYSeries;
import de.intevation.flys.utils.ThemeUtil;
import de.intevation.flys.utils.FLYSUtils;

import de.intevation.flys.model.Gauge;
import de.intevation.flys.model.River;

import org.jfree.chart.plot.Marker;
import org.jfree.chart.plot.ValueMarker;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;

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.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.XYSeries;
import org.w3c.dom.Document;

/**
 * Generator for WQ fixing charts.
 * @author <a href="mailto:christian.lins@intevation.de">Christian Lins</a>
 */
public class FixWQCurveGenerator
extends      FixChartGenerator
implements   FacetTypes
{
    private static Logger logger =
        Logger.getLogger(FixWQCurveGenerator.class);

    public static final String I18N_CHART_TITLE =
        "chart.fixings.wq.title";

    public static final String I18N_CHART_SUBTITLE =
        "chart.fixings.wq.subtitle";

    public static final String I18N_CHART_SUBTITLE1 =
        "chart.fixings.wq.subtitle1";

    public static final String I18N_XAXIS_LABEL =
        "chart.fixings.wq.xaxis.label";

    public static final String I18N_YAXIS_LABEL =
        "chart.fixings.wq.yaxis.label";

    public static final String I18N_CHART_TITLE_DEFAULT  =
        "Fixierungsanalyse";

    public static final String I18N_XAXIS_LABEL_DEFAULT  =
        "Q [m\u00B3/s]";

    public static final String I18N_YAXIS_LABEL_DEFAULT  =
        "W [NN + m]";

    public static enum YAXIS {
        W(0),
        Q(1);
        public int idx;
        private YAXIS(int c) {
            idx = c;
        }
    }


    private FLYSArtifact artifact;


    @Override
    public void doOut(ArtifactAndFacet aaf, Document doc, boolean visible) {
        String name = aaf.getFacetName();
        logger.debug("doOut: " + name);

        this.artifact = (FLYSArtifact)aaf.getArtifact();

        if(name.startsWith(FIX_SECTOR_AVERAGE_WQ)) {
            doSectorAverageOut(aaf, doc, visible);
        }
        else if(FIX_ANALYSIS_EVENTS_WQ.equals(name)) {
            doAnalysisEventsOut(aaf, doc, visible);
        }
        else if(FIX_REFERENCE_EVENTS_WQ.equals(name)) {
            doReferenceEventsOut(aaf, doc, visible);
        }
        else if(FIX_WQ_CURVE.equals(name)) {
            doWQCurveOut(aaf, doc, visible);
        }
        else if(FIX_OUTLIER.equals(name)) {
            doOutlierOut(aaf, doc, visible);
        }
        else if(QSECTOR.equals(name)) {
            doQSectorOut(aaf, doc, visible);
        }
        else if(STATIC_WKMS_INTERPOL.equals(name) ||
                STATIC_WKMS.equals(name) ||
                HEIGHTMARKS_POINTS.equals(name) ) {
            doWAnnotations(
                    aaf.getData(context),
                    aaf,
                    doc,
                    visible);
        }
        if (LONGITUDINAL_W.equals(name) || STATIC_WQ.equals(name)) {
            doWQOut(aaf.getData(context), aaf, doc, visible);
        }
        else if (name.equals(DISCHARGE_CURVE)) {
            doDischargeOut(
                (WINFOArtifact) aaf.getArtifact(),
                aaf.getData(context),
                aaf.getFacetDescription(),
                doc,
                visible);
        }
        else {
            logger.warn("Unknown facet name " + name);
            return;
        }
    }

    /** Add sector average points to chart */
    protected void doSectorAverageOut(ArtifactAndFacet aaf, Document doc, boolean visible) {
        logger.debug("doSectorAverageOut");

        QWDDateRange qwdd = (QWDDateRange) aaf.getData(context);
        QWD qwd = qwdd != null ? qwdd.getQWD() : null;

        if(qwd != null) {
            addQWSeries(new QWD[] { qwd }, aaf, doc, visible);
        }
        else {
            logger.debug("doSectorAverageOut: qwd == null");
        }
    }

    /** Add analysis event points to chart */
    protected void doAnalysisEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) {
        logger.debug("doAnalysisEventsOut");

        QWD[] qwds = (QWD[])aaf.getData(context);
        if(qwds != null) {
            addQWSeries(qwds, aaf, doc, visible);
        }
        else {
            logger.debug("doAnalysisEventsOut: qwds == null");
        }
    }

    /** Add reference event points to chart */
    protected void doReferenceEventsOut(ArtifactAndFacet aaf, Document doc, boolean visible) {
       logger.debug("doReferenceEventsOut");

       QW[] qws = (QW[])aaf.getData(context);
       addQWSeries(qws, aaf, doc, visible);
    }

    protected void doWQCurveOut(ArtifactAndFacet aaf, Document doc, boolean visible) {
        logger.debug("doWQCurveOut");

        FixWQCurveFacet facet = (FixWQCurveFacet)aaf.getFacet();
        FixFunction func = (FixFunction)facet.getData(
            aaf.getArtifact(), context);

        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(),
                doc,
                aaf.getFacetDescription(),
                500,   // number of samples
                0.0 ,  // start
                maxQ); // end

            addAxisSeries(series, 0, visible);
        }
        else {
            logger.warn("doWQCurveOut: maxQ <= 0");
        }
    }

    protected void doOutlierOut(ArtifactAndFacet aaf, Document doc, boolean visible) {
        logger.debug("doOutlierOut");

        QW[] qws = (QW[])aaf.getData(context);
        addQWSeries(qws, aaf, doc, visible);
    }


    /** Add markers for q sectors. */
    protected void doQSectorOut(ArtifactAndFacet aaf, Document theme, boolean visible) {
        logger.debug("doQSectorOut");
        if (!visible) {
            return;
        }

        List<NamedDouble> qsectors = (List<NamedDouble>) aaf.getData(context);

        if (qsectors == null) {
            logger.warn("No QSectors coming from data.");
            return;
        }
        for (NamedDouble qsector : qsectors) {
            if (Double.isNaN(qsector.getValue())) {
                continue;
            }
            Marker m = new ValueMarker(qsector.getValue());
            m.setPaint(Color.black);

            float[] dashes = ThemeUtil.parseLineStyle(theme);
            int size       = ThemeUtil.parseLineWidth(theme);
            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 (ThemeUtil.parseShowLineLabel(theme)) {
                m.setLabel(qsector.getName());
                m.setPaint(ThemeUtil.parseTextColor(theme));
                m.setLabelFont(ThemeUtil.parseTextFont(theme));
            }
            Color paint = ThemeUtil.parseLineColorField(theme);
            if (paint != null) {
                m.setPaint(paint);
            }
            m.setLabelAnchor(RectangleAnchor.TOP_LEFT);
            m.setLabelTextAnchor(TextAnchor.TOP_LEFT);
            addDomainMarker(m);
        }
    }


    /**
     * Add W-Annotations to plot.
     * @param wqkms actual data (double[][]).
     * @param theme theme to use.
     */
    protected void doWAnnotations(
        Object   wqkms,
        ArtifactAndFacet aandf,
        Document theme,
        boolean  visible
    ) {
        Facet facet = aandf.getFacet();

        List<StickyAxisAnnotation> xy = new ArrayList<StickyAxisAnnotation>();
        if (wqkms instanceof double[][]) {
            logger.debug("Got double[][]");
            double [][] data = (double [][]) wqkms;
            for (int i = 0; i< data[0].length; i++) {
                xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(),
                    (float) data[1][i], StickyAxisAnnotation.SimpleAxis.Y_AXIS));
            }

            doAnnotations(new FLYSAnnotation(facet.getDescription(), xy),
                aandf, theme, visible);
        }
        else {
            // Assume its WKms.
            logger.debug("Got WKms");
            WKms data = (WKms) wqkms;

            Double ckm = (Double) context.getContextValue(CURRENT_KM);
            double location = (ckm != null)
                              ? ckm.doubleValue()
                              : getRange()[0];
            double w = ((StaticWKmsArtifact) aandf.getArtifact())
                .getWAtKmLin(data, location);
            xy.add(new StickyAxisAnnotation(aandf.getFacetDescription(),
              (float) w, StickyAxisAnnotation.SimpleAxis.Y_AXIS));

            doAnnotations(new FLYSAnnotation(facet.getDescription(), xy),
                aandf, theme, visible);
        }
    }


    /**
     * Add series with discharge curve to diagram.
     */
    protected void doDischargeOut(
        WINFOArtifact artifact,
        Object        o,
        String        description,
        Document      theme,
        boolean       visible)
    {
        WQKms wqkms = (WQKms) o;

        String gaugeName = wqkms.getName();

        River river = FLYSUtils.getRiver(artifact);

        if (river == null) {
            logger.debug("no river found");
            return;
        }

        Gauge gauge = river.determineGaugeByName(gaugeName);

        if (gauge == null) {
            logger.debug("no gauge found");
            return;
        }

        XYSeries series = new StyledXYSeries(description, theme);

        StyledSeriesBuilder.addPointsQW(series, wqkms);

        addAxisSeries(series, YAXIS.W.idx, visible);
    }


    /**
     * Add WQ Data to plot.
     * @param wqkms data as double[][]
     */
    protected void doWQOut(
        Object           wqkms,
        ArtifactAndFacet aaf,
        Document         theme,
        boolean          visible
    ) {
        logger.debug("FixWQCurveGenerator: doWQOut");
        if (wqkms instanceof WQKms) {
            WQKms data = (WQKms) wqkms;

            XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
            Double ckm = (Double) context.getContextValue(CURRENT_KM);

            StyledSeriesBuilder.addPointsQW(series, data);

            addAxisSeries(series, YAXIS.W.idx, visible);
        }
        else {
            double [][] data = (double [][]) wqkms;

            XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
            StyledSeriesBuilder.addPoints(series, data, true);

            addAxisSeries(series, YAXIS.W.idx, visible);
        }
    }


    protected void addQWSeries(QW[] qws, ArtifactAndFacet aaf, Document theme, boolean visible) {
         if(qws != null) {
            XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
            List<XYTextAnnotation> textAnnos = new ArrayList<XYTextAnnotation>();

            DateFormat dateFormat = DateFormat.getDateInstance(
                DateFormat.SHORT);

            for(QW qw : qws) {
                series.add(qw.getQ(), qw.getW());

                XYTextAnnotation anno = new CollisionFreeXYTextAnnotation(
                    dateFormat.format(qw.getDate()),
                    qw.getQ(),
                    qw.getW());
                textAnnos.add(anno);
            }

            addAxisSeries(series, 0, visible);
            if(visible && ThemeUtil.parseShowPointLabel(theme)) {
                FLYSAnnotation flysAnno = new FLYSAnnotation(null, null, null, theme);
                flysAnno.setTextAnnotations(textAnnos);
                addAnnotations(flysAnno);
            }
        }
    }

    @Override
    protected String getChartTitle() {
        return Resources.format(
                context.getMeta(),
                I18N_CHART_TITLE,
                I18N_CHART_TITLE_DEFAULT,
                context.getContextValue(CURRENT_KM));
    }

    @Override
    protected String getDefaultChartTitle() {
        return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
    }

    @Override
    protected String getDefaultChartSubtitle() {
        FixAnalysisAccess access = new FixAnalysisAccess(artifact);
        DateRange dateRange = access.getDateRange();
        DateRange refRange  = access.getReferencePeriod();

        if (dateRange != null && refRange != null) {
            return Resources.format(
                    context.getMeta(),
                    I18N_CHART_SUBTITLE,
                    "",
                    access.getRiver(),
                    dateRange.getFrom(),
                    dateRange.getTo(),
                    refRange.getFrom(),
                    refRange.getTo());
        }

        return null;
    }

    @Override
    protected void addSubtitles(JFreeChart chart) {
        String defaultSubtitle = getDefaultChartSubtitle();

        if (defaultSubtitle == null || defaultSubtitle.length() == 0) {
            return;
        }

        chart.addSubtitle(new TextTitle(defaultSubtitle));

        StringBuilder buf = new StringBuilder();

        // Add analysis periods as additional subtitle
        FixAnalysisAccess access = new FixAnalysisAccess(artifact);
        DateRange[] aperiods = access.getAnalysisPeriods();
        buf.append(msg("fix.analysis.periods"));
        buf.append(": ");
        for(int n = 0; n < aperiods.length; n++) {
            buf.append(
                    Resources.format(
                            context.getMeta(),
                            I18N_CHART_SUBTITLE1,
                            "",
                            aperiods[n].getFrom(),
                            aperiods[n].getTo()));
            if(n + 1 < aperiods.length) {
                buf.append("; ");
            }
        }

        chart.addSubtitle(new TextTitle(buf.toString()));
    }

    @Override
    protected String getDefaultXAxisLabel() {
        return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
    }

    @Override
    protected String getDefaultYAxisLabel(int pos) {
        return msg(I18N_YAXIS_LABEL, I18N_YAXIS_LABEL_DEFAULT);
    }

    @Override
    protected ChartGenerator.YAxisWalker getYAxisWalker() {
        return new YAxisWalker() {
            @Override
            public int length() {
                return YAXIS.values().length;
            }

            @Override
             public String getId(int idx) {
                YAXIS[] yaxes = YAXIS.values();
                return yaxes[idx].toString();
            }
        };
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org