view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/Calculation6.java @ 4255:670e98f5a441

Fixed leak while merging facets. The ThemeList that is used by OutputHelper to sort the Facets for an Output now uses a list to store the ManagedFacets. The correct order is made up by sorting the List using Collections.sort() function of the Java JDK. Therfore, the ManagedFacet class implements the Comparable interface. The return value of its compareTo(other) method depends on the value of the 'position' field.
author Ingo Weinzierl <weinzierl.ingo@googlemail.com>
date Thu, 25 Oct 2012 14:01:46 +0200
parents 49cb65d5932d
children 7b6c31390427
line wrap: on
line source
package de.intevation.flys.artifacts.model;

import java.util.ArrayList;
import java.util.Arrays;
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 = prepareTimerangeData(refTable, dts);
        WQKms[] wqs = prepareWQData(dts);

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

        return new CalculationResult(new HistoricalDischargeData(wqt, wqs),
            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[] prepareTimerangeData(DischargeTable refTable,
        List<DischargeTable> dts) {
        if (refTable == null) {
            addProblem("cannot.find.hist.q.reftable");
            return prepareSimpleData(dts);
        }
        else {
            return prepareData(refTable, dts);
        }
    }

    protected WQKms[] prepareWQData(List<DischargeTable> dts) {
        WQKms[] wqs = new WQKms[dts.size()];

        int idx = 0;

        for (DischargeTable dt : dts) {
            double[][] values = null;

            if (dt.getKind() == DischargeTables.MASTER) {
                values = DischargeTables.loadDischargeTableValues(dt,
                    DischargeTables.MASTER_SCALE);

            }
            else {
                values = DischargeTables.loadDischargeTableValues(dt,
                    DischargeTables.HISTORICAL_SCALE);

            }

            wqs[idx++] = prepareWQ(dt, values);
        }

        return wqs;
    }

    protected WQKms prepareWQ(DischargeTable dt, double[][] values) {
        double km = dt.getGauge().getStation().doubleValue();

        double[] kms = new double[values[0].length];
        Arrays.fill(kms, km);

        return new HistoricalWQKms(kms, values[1], values[0],
            String.valueOf(km), dt.getTimeInterval());
    }

    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, DischargeTables.HISTORICAL_SCALE);
                }

                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,
                    DischargeTables.MASTER_SCALE);
            }
            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, DischargeTables.HISTORICAL_SCALE);

                    if (Double.isNaN(w)) {
                        logger.warn("Cannot find W for Q: " + q);
                        addProblem("cannot.find.hist.w.for.q", q, ti[0], ti[1]);
                        continue;
                    }
                    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 scale) {
        double[][] vs = DischargeTables.loadDischargeTableValues(dt, scale);
        double[] ws = DischargeTables.getWsForQ(vs, q);

        return ws.length == 0 ? Double.NaN : ws[0];
    }

    /**
     * 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