Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java @ 9176:1614cb14308f
Work on calculations for S-Info flood duration workflow
author | mschaefer |
---|---|
date | Mon, 25 Jun 2018 19:21:11 +0200 |
parents | |
children | a4121ec450d6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/common/GaugeDurationValuesFinder.java Mon Jun 25 19:21:11 2018 +0200 @@ -0,0 +1,152 @@ +/** 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 = "ca."; // "\u2248" geht wohl nicht + + + /***** 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; + } + } +} \ No newline at end of file