view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java @ 4187:21f4e4b79121

Refactor GaugeDischargeCurveFacet to be able to set a facet name For adding another output of the GaugeDischargeCurveArtifact it is necessary to provide to facet instances with different names. Therefore the GaugeDischargeCurveFacet is extended to set the facet name in the constructor.
author Björn Ricks <bjoern.ricks@intevation.de>
date Fri, 19 Oct 2012 13:25:49 +0200
parents 1d9c9a3493ea
children b3aa91e45010
line wrap: on
line source
package de.intevation.flys.artifacts.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import de.intevation.flys.model.DischargeTable;
import de.intevation.flys.model.Gauge;
import de.intevation.flys.model.TimeInterval;


/**
 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
 */
public class Calculation6 extends Calculation {

    private static final Logger logger = Logger.getLogger(Calculation6.class);

    private int      mode;
    private long[]   timerange;
    private double[] values;


    public static final int MODE_W = 0;
    public static final int MODE_Q = 1;

    public static final double SCALE = 1d;


    public Calculation6(int mode, long[] timerange, double[] values) {
        this.mode      = mode;
        this.timerange = timerange;
        this.values    = values;
    }


    public CalculationResult calculate(Gauge gauge) {
        if (!checkParameters() || gauge == null) {
            logger.warn("Parameters not valid for calculation.");

            return null;
        }

        if (logger.isDebugEnabled()) {
            debug();
        }

        DischargeTable  refTable = fetchReferenceTable(gauge);
        List<DischargeTable> dts = fetchDischargeTables(gauge);

        int numTables = dts.size();

        logger.debug("Take " + numTables + " into account.");

        if (numTables == 0) {
            addProblem("cannot.find.hist.q.tables");
        }

        WQTimerange[] wqt = prepareCalculationData(refTable, dts);

        logger.debug("Number of calculation results: " + wqt.length);

        return new CalculationResult(wqt, this);
    }


    protected boolean checkParameters() {
        if (!(mode == MODE_W || mode == MODE_Q)) {
            logger.warn("Invalid mode '" + mode + "' for calculation.");
            return false;
        }

        if (timerange == null || timerange.length < 2) {
            logger.warn("Invalid timerange for calculation.");
            return false;
        }

        if (values == null || values.length == 0) {
            logger.warn("No values for W or Q specified.");
            return false;
        }

        return true;
    }


    protected DischargeTable fetchReferenceTable(Gauge gauge) {
        return gauge.fetchMasterDischargeTable();
    }


    protected List<DischargeTable> fetchDischargeTables(Gauge gauge) {
        List<DischargeTable> relevant = new ArrayList<DischargeTable>();
        List<DischargeTable> all      = gauge.getDischargeTables();

        for (DischargeTable dt: all) {
            if (isDischargeTableRelevant(dt)) {
                relevant.add(dt);
            }
        }

        return relevant;
    }


    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();

        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;
        }

        logger.debug("DischargeTable not in range: " + start + " -> " + stop);

        return false;
    }


    protected WQTimerange[] prepareCalculationData(
        DischargeTable       refTable,
        List<DischargeTable> dts
    ) {
        if (refTable == null) {
            addProblem("cannot.find.hist.q.reftable");
            return prepareSimpleData(dts);
        }
        else {
            return prepareData(refTable, dts);
        }
    }


    protected WQTimerange[] prepareSimpleData(List<DischargeTable> dts) {
        List<WQTimerange> wqts =
            new ArrayList<WQTimerange>(values.length);

        for (double value: values) {
            logger.debug("Prepare data for value: " + value);

            String name      = mode == MODE_W ? "W=" + value : "Q=" + value;
            WQTimerange wqt  = null;

            for (DischargeTable dt: dts) {
                Date[]   ti = prepareTimeInterval(dt);
                Timerange t = new Timerange(ti[0], ti[1]);
                double    w;
                double    q;

                if (mode == MODE_W) {
                    w = value;
                    q = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE);

                    if (Double.isNaN(q)) {
                        logger.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);
                }

                logger.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()]);
    }


    protected HistoricalWQTimerange[] prepareData(
        DischargeTable       refTable,
        List<DischargeTable> dts
    ) {
        List<HistoricalWQTimerange> wqts =
            new ArrayList<HistoricalWQTimerange>(values.length);

        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;
            double diff;

            if (refTable != null && mode == MODE_W) {
                ref = findValueForW(refTable, value, DischargeTables.MASTER_SCALE);
            }
            else if (refTable != null) {
                ref = findValueForQ(refTable, value);
            }
            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 == MODE_W) {
                    w    = value;
                    q    = findValueForW(dt, w, DischargeTables.HISTORICAL_SCALE);

                    if (Double.isNaN(q)) {
                        logger.warn("Cannot find Q for W: " + w);
                        addProblem("cannot.find.hist.q.for.w", w, ti[0], ti[1]);
                        continue;
                    }

                    diff = ref-q;
                }
                else {
                    q    = value;
                    w    = findValueForQ(dt, q);
                    diff = ref-w;
                }

                logger.debug("Q=" + q + " | W=" + w + " | Ref = " + ref);

                if (wqt == null) {
                    wqt = new HistoricalWQTimerange(name);
                }

                wqt.add(w, q, diff, t);
            }

            if (wqt != null) {
                wqts.add(wqt);
            }
        }

        return (HistoricalWQTimerange[])
            wqts.toArray(new HistoricalWQTimerange[wqts.size()]);
    }


    protected Date[] prepareTimeInterval(DischargeTable dt) {
        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();
        }

        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[][] vs = DischargeTables.loadDischargeTableValues(dt, SCALE);
        logger.warn("TODO: IMPLEMENT ME!");

        return 10;
    }


    /**
     * Writes the parameters used for this calculation to logger.
     */
    public void debug() {
        StringBuilder sb = new StringBuilder();
        for (double value: values) {
            sb.append(String.valueOf(value) + " ");
        }

        logger.debug("========== Calculation6 ==========");
        logger.debug("   Mode:         " + mode);
        logger.debug("   Timerange:    " + timerange[0] + " - " + timerange[1]);
        logger.debug("   Input values: " + sb.toString());
        logger.debug("==================================");
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org