view artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java @ 9195:a4121ec450d6

'ca.'-issue ExportContextCSV+PDF separated uinfo.inundationduration url export
author gernotbelger
date Fri, 29 Jun 2018 14:52:54 +0200
parents 1614cb14308f
children b4402594213b
line wrap: on
line source
/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
 * Software engineering by
 *  Björnsen Beratende Ingenieure GmbH
 *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
 *
 * This file is Free Software under the GNU AGPL (>=v3)
 * and comes with ABSOLUTELY NO WARRANTY! Check out the
 * documentation coming with Dive4Elements River for details.
 */
package org.dive4elements.river.artifacts.sinfo.common;

import org.apache.commons.lang.math.DoubleRange;
import org.apache.commons.math.FunctionEvaluationException;
import org.apache.commons.math.analysis.UnivariateRealFunction;
import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
import org.dive4elements.river.artifacts.model.Calculation;
import org.dive4elements.river.model.Gauge;
import org.dive4elements.river.model.MainValue;
import org.dive4elements.river.model.MainValueType.MainValueTypeKey;

import gnu.trove.TDoubleArrayList;

/**
 * Loading and search/interpolate the duration main values of a gauge
 *
 * @author Matthias Schäfer
 *
 */
public final class GaugeDurationValuesFinder {

    /***** FIELDS *****/

    // private static Logger log = Logger.getLogger(GaugeDurationValuesFinder.class);

    private final Gauge gauge;

    private Calculation problems;

    private UnivariateRealFunction qInterpolator;

    private DoubleRange qRange;

    private UnivariateRealFunction durInterpolator;

    private DoubleRange durRange;

    private final String approxPrefix = "\u2248";// "ca.";

    /***** CONSTRUCTORS *****/

    private GaugeDurationValuesFinder(final Gauge gauge, final Calculation problems) {
        this.gauge = gauge;
        this.problems = problems;
        final TDoubleArrayList qs = new TDoubleArrayList();
        final TDoubleArrayList durs = new TDoubleArrayList();
        for (final MainValue v : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.DURATION)) {
            qs.add(v.getValue().doubleValue());
            durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
        }
        try {
            this.qInterpolator = new LinearInterpolator().interpolate(qs.toNativeArray(), durs.toNativeArray());
            this.qRange = new DoubleRange(qs.get(0), qs.get(qs.size() - 1));
        }
        catch (final Exception e) {
            this.qInterpolator = null;
            this.qRange = null;
        }
        qs.clear();
        durs.clear();
        for (final MainValue v : MainValue.getDurationDischargesOfGauge(gauge)) {
            durs.add(Integer.valueOf(v.getMainValue().getName()).doubleValue());
            qs.add(v.getValue().doubleValue());
        }
        try {
            this.durInterpolator = new LinearInterpolator().interpolate(durs.toNativeArray(), qs.toNativeArray());
            this.durRange = new DoubleRange(durs.get(0), durs.get(durs.size() - 1));
        }
        catch (final Exception e) {
            this.durInterpolator = null;
            this.durRange = null;
        }
        if (((this.qInterpolator == null) || (this.durInterpolator == null)) && (this.problems != null)) {
            this.problems.addProblem("gauge_duration.missing", gauge.getName());
            // Report only once
            this.problems = null;
        }
    }

    /***** METHODS *****/

    /**
     * Loads the the discharge-duration table of a gauge (GAUGE.glt)
     *
     * @return The main values finder of a a gauge, or null
     */
    public static GaugeDurationValuesFinder loadValues(final Gauge gauge, final Calculation problems) {
        return new GaugeDurationValuesFinder(gauge, problems);
    }

    /**
     * If this provider may return valid data at all.
     */
    public boolean isValid() {
        return (this.qInterpolator != null);
    }

    /**
     * Discharge for a duration
     *
     * @return Q, or NegInf for duration less than all, or PosInf for duration greater then all, or NaN in case of exception
     */
    public double getDischarge(final int duration) {
        try {
            if (this.durInterpolator == null)
                return Double.NaN;
            else if (duration < this.durRange.getMinimumDouble())
                return Double.NEGATIVE_INFINITY;
            else if (duration > this.durRange.getMaximumDouble())
                return Double.POSITIVE_INFINITY;
            else
                return this.durInterpolator.value(duration);
        }
        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
            // ignore exception because this can/will happen regularly
            return Double.NaN;
        }
    }

    /**
     * Duration for a discharge
     *
     * @return duration, or 0 for Q less than all, or 365 for duration greater then all, or -1 in case of exception
     */
    public double getDuration(final double q) {
        try {
            if (this.qInterpolator == null)
                return -1;
            else if (q < this.qRange.getMinimumDouble())
                return 0;
            else if (q > this.qRange.getMaximumDouble())
                return 365;
            else
                return this.qInterpolator.value(q);
        }
        catch (@SuppressWarnings("unused") final FunctionEvaluationException e) {
            // ignore exception because this can/will happen regularly
            return -1;
        }
    }
}

http://dive4elements.wald.intevation.org