changeset 9266:465347d12990

Station specific calculation of flood duration curve and infrastructure annotations
author mschaefer
date Wed, 18 Jul 2018 12:20:01 +0200
parents e5367900dd6d
children c7e5285d434f
files artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java
diffstat 6 files changed, 184 insertions(+), 49 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java	Tue Jul 17 19:48:28 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java	Wed Jul 18 12:20:01 2018 +0200
@@ -9,11 +9,14 @@
  */
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
+import java.util.List;
+
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.WINFOArtifact;
 import org.dive4elements.river.artifacts.model.Calculation;
 import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
@@ -21,6 +24,7 @@
 import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper;
 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
+import org.dive4elements.river.jfree.StickyAxisAnnotation;
 import org.dive4elements.river.model.River;
 
 /**
@@ -74,4 +78,40 @@
         final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, riverInfoProvider);
         calculator.execute(problems, label, calcRange, riverside, winfo, results);
     }
+
+    /**
+     * Calculates the flood duration curve of a station
+     */
+    public WQDay calcStationCurve(final double station, final SINFOArtifact sinfo) {
+
+        /* access input data */
+        final FloodDurationAccess access = new FloodDurationAccess(sinfo);
+        final River river = access.getRiver();
+        final DoubleRange calcRange = access.getRange();
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
+
+        final Calculation problems = new Calculation();
+
+        // Calculate the selected main values, if any
+        /* misuse winfo-artifact to calculate waterlevels in the same way */
+        final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
+        winfo.addStringData("ld_locations", Double.toString(station));
+
+        final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, infoProvider);
+        if (!Double.isNaN(station))
+            return calculator.calcWQDays(problems, station, winfo);
+        else
+            return calculator.calcWQDays(problems, calcRange.getMinimumFloat(), winfo);
+    }
+
+    /**
+     * Calculates the annotations of the infrastructure(s) of a station for a flood duration calculation
+     */
+    public List<StickyAxisAnnotation> calcInfrastructureAnnotations(final double station, final FloodDurationCalculationResult result) {
+
+        final Calculation problems = new Calculation();
+
+        final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, null);
+        return calculator.calcInfrastructureAnnotations(problems, station, result);
+    }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java	Tue Jul 17 19:48:28 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java	Wed Jul 18 12:20:01 2018 +0200
@@ -53,23 +53,23 @@
         return this.mainValueQAnnotations;
     }
 
-    private StickyAxisAnnotation infrastructureWAnnotation;
-
-    public StickyAxisAnnotation getInfrastructureWAnnotation() {
-        return this.infrastructureWAnnotation;
-    }
-
-    public void setInfrastructureWAnnotation(final StickyAxisAnnotation infrastructureWAnnotation) {
-        this.infrastructureWAnnotation = infrastructureWAnnotation;
-    }
-
-    private StickyAxisAnnotation infrastructureQAnnotation;
-
-    public StickyAxisAnnotation getInfrastructureQAnnotation() {
-        return this.infrastructureQAnnotation;
-    }
-
-    public void setInfrastructureQAnnotation(final StickyAxisAnnotation infrastructureQAnnotation) {
-        this.infrastructureQAnnotation = infrastructureQAnnotation;
-    }
+    // private StickyAxisAnnotation infrastructureWAnnotation;
+    //
+    // public StickyAxisAnnotation getInfrastructureWAnnotation() {
+    // return this.infrastructureWAnnotation;
+    // }
+    //
+    // public void setInfrastructureWAnnotation(final StickyAxisAnnotation infrastructureWAnnotation) {
+    // this.infrastructureWAnnotation = infrastructureWAnnotation;
+    // }
+    //
+    // private StickyAxisAnnotation infrastructureQAnnotation;
+    //
+    // public StickyAxisAnnotation getInfrastructureQAnnotation() {
+    // return this.infrastructureQAnnotation;
+    // }
+    //
+    // public void setInfrastructureQAnnotation(final StickyAxisAnnotation infrastructureQAnnotation) {
+    // this.infrastructureQAnnotation = infrastructureQAnnotation;
+    // }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Tue Jul 17 19:48:28 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Wed Jul 18 12:20:01 2018 +0200
@@ -10,6 +10,7 @@
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -118,18 +119,17 @@
             mainValueLabels[i] = wqkmsArray[i].getName();
         results.addResult(new FloodDurationCalculationResult(label, mainValueLabels, this.rows), problems);
 
-        calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results);
-
-        calcMainValueAnnotations(problems, 0, AttributeKey.LEFT, wqkmsArray, results);
-
-        calcInfrastructureAnnotations(problems, this.rows.get(0), wqkmsArray, results);
+        // calcWQDays(problems, stationsSorted[0], AttributeKey.LEFT, winfo, results);
+        //
+        // calcMainValueAnnotations(problems, 0, AttributeKey.LEFT, wqkmsArray, results);
+        //
+        // calcInfrastructureAnnotations(problems, this.rows.get(0), wqkmsArray, results);
     }
 
     /**
-     * Calculate duration curve for a station and add to result collection
+     * Calculates the duration curve for a station
      */
-    private void calcWQDays(final Calculation problems, final double station, final AttributeKey riverside, final WINFOArtifact winfo,
-            final FloodDurationCalculationResults results) {
+    public WQDay calcWQDays(final Calculation problems, final double station, final WINFOArtifact winfo) {
 
         // Same processing as in W-Info DurationCurveState
         winfo.addStringData("ld_locations", Double.toString(station));
@@ -144,13 +144,13 @@
             ws[j] = underflow.getW(i);
             qs[j] = underflow.getQ(i);
         }
-        results.setDurationCurve(new WQDay(days, ws, qs));
+        return new WQDay(days, ws, qs);
     }
 
     /**
      * Calculate the data for the W and Q main value lines in the duration curve chart and add to result collection
      */
-    private void calcMainValueAnnotations(final Calculation problems, final int stationIndex, final AttributeKey riverside,
+    public void calcMainValueAnnotations(final Calculation problems, final int stationIndex, final AttributeKey riverside,
             final WQKms[] wqkmsArray, final FloodDurationCalculationResults results) {
 
         // Same way as in MainValueWFacet and ..QFacet, but special label handling
@@ -178,28 +178,70 @@
      * Calculate the data for the W and Q lines in the duration curve chart for the infrastructure height and add to result
      * collection
      */
-    private void calcInfrastructureAnnotations(final Calculation problems, final ResultRow row, final WQKms[] wqkmsArray,
-            final FloodDurationCalculationResults results) {
+    public List<StickyAxisAnnotation> calcInfrastructureAnnotations(final Calculation problems, final double station,
+            final FloodDurationCalculationResult result) {
 
-        if (row.getValue(SInfoResultType.infrastructuretype) == null) {
-            results.setInfrastructureWAnnotation(null);
-            results.setInfrastructureQAnnotation(null);
-            return;
+        // Search the station in the previously calculated result rows and terminate if no infrastructure row found
+        double station1 = station;
+        if (Double.isNaN(station)) {
+            for (final ResultRow row : result.getRows()) {
+                station1 = row.getDoubleValue(GeneralResultType.station);
+                break;
+            }
+        }
+        final List<ResultRow> stationRows = searchStation(station1, result.getRows());
+        if (stationRows.isEmpty() || (stationRows.get(0).getValue(SInfoResultType.infrastructuretype) == null)) {
+            return null;
         }
         // Same way as in MainValueWFacet and ..QFacet
+        final List<StickyAxisAnnotation> annotations = new ArrayList<>();
+        for (final ResultRow row : stationRows) {
+            annotations.add(calcWAnnotation(row));
+            annotations.add(calcQAnnotation(row));
+        }
+        return annotations;
+    }
+
+    /**
+     * Searches the one or two rows of a station in a result rows collection
+     */
+    private List<ResultRow> searchStation(final double station, final Collection<ResultRow> rows) {
+        final List<ResultRow> found = new ArrayList<>();
+        for (final ResultRow row : rows) {
+            if (row.getDoubleValue(GeneralResultType.station) > station + 0.0001)
+                break;
+            else if (row.getDoubleValue(GeneralResultType.station) > station - 0.0001)
+                found.add(row);
+        }
+        return found;
+    }
+
+    /**
+     * Calculates the Q annotation lines of an infrastructure
+     */
+    private StickyAxisAnnotation calcQAnnotation(final ResultRow row) {
         final String label = Resources.getMsg(this.context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure",
                 "sinfo.chart.flood_duration.curve.infrastructure",
                 SInfoResultType.infrastructuretype.exportValue(this.context, row.getValue(SInfoResultType.infrastructuretype))
                 + ", " + SInfoResultType.riverside.exportValue(this.context, row.getValue(SInfoResultType.riverside)));
-        final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge),
+        final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge),
                 SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.Q.idx);
-        FloodDurationMainValuesQFacet.setHitPoint(results.getDurationCurve(), qAnnotation);
-        final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight),
+        annotation.setHitPoint((float) row.getDoubleValue(SInfoResultType.floodDuration));
+        return annotation;
+    }
+
+    /**
+     * Calculates the W annotation lines of an infrastructure
+     */
+    private StickyAxisAnnotation calcWAnnotation(final ResultRow row) {
+        final String label = Resources.getMsg(this.context.getMeta(), "sinfo.chart.flood_duration.curve.infrastructure",
+                "sinfo.chart.flood_duration.curve.infrastructure",
+                SInfoResultType.infrastructuretype.exportValue(this.context, row.getValue(SInfoResultType.infrastructuretype))
+                + ", " + SInfoResultType.riverside.exportValue(this.context, row.getValue(SInfoResultType.riverside)));
+        final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight),
                 SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.W.idx);
-        FloodDurationMainValuesWFacet.setHitPoint(results.getDurationCurve(), wAnnotation);
-
-        results.setInfrastructureQAnnotation(qAnnotation);
-        results.setInfrastructureWAnnotation(wAnnotation);
+        annotation.setHitPoint((float) row.getDoubleValue(SInfoResultType.floodDuration));
+        return annotation;
     }
 
     /**
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java	Tue Jul 17 19:48:28 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java	Wed Jul 18 12:20:01 2018 +0200
@@ -17,6 +17,7 @@
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
 
 
@@ -59,7 +60,8 @@
         // TODO: entweder in data.getDurationCurve() reingeben, oder bei FloodDurationCalculationResults auswerten...
         // TODO: was ist aus perfromanz/speicher-sicht besser?
 
-        return data.getDurationCurve();
+        // return data.getDurationCurve();
+        return new FloodDurationCalculation(context).calcStationCurve(currentKm, (SINFOArtifact) flys);
     }
 
     /**
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java	Tue Jul 17 19:48:28 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java	Wed Jul 18 12:20:01 2018 +0200
@@ -10,7 +10,8 @@
 
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
-import java.util.ArrayList;
+import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
+
 import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -60,17 +61,42 @@
 
         final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
 
-        final List<StickyAxisAnnotation> annotations = new ArrayList<>();
-        annotations.add(data.getInfrastructureWAnnotation());
-        annotations.add(data.getInfrastructureQAnnotation());
-        if (annotations.get(0) != null) {
-            this.description = annotations.get(0).getText(); // TODO Diagramm-Aktualisierung auslösen
+        // final List<StickyAxisAnnotation> annotations = new ArrayList<>();
+        // annotations.add(data.getInfrastructureWAnnotation());
+        // annotations.add(data.getInfrastructureQAnnotation());
+
+        final double currentKm = getCurrentKm(context);
+
+        final List<StickyAxisAnnotation> annotations = new FloodDurationCalculation(context).calcInfrastructureAnnotations(currentKm,
+                data.getResults().get(this.index));
+        if (annotations != null) {
             return new RiverAnnotation(this.description, annotations);
         }
         else
             return null;
     }
 
+    /**
+     * Returns the current km from the context.
+     * If the context is null or doesn't contain a currentKm
+     * then a double value of -1 will be returned.
+     *
+     * @param context
+     *            The CallContext instance
+     * @return the current km as double
+     */
+    // FIXME: copied from org.dive4elements.river.artifacts.model.fixings.FixingsFacet
+    private double getCurrentKm(final CallContext context) {
+        if (context == null)
+            return Double.NaN;
+
+        final Double dkm = (Double) context.getContextValue(CURRENT_KM);
+        if (dkm == null)
+            return Double.NaN;
+
+        return dkm.doubleValue();
+    }
+
 
     /**
      * Create a deep copy of this Facet.
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java	Tue Jul 17 19:48:28 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java	Wed Jul 18 12:20:01 2018 +0200
@@ -8,6 +8,8 @@
 
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
+import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
+
 import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.state.DefaultFacet;
 import org.dive4elements.artifacts.Artifact;
@@ -71,9 +73,32 @@
 
         final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
 
+        final double currentKm = getCurrentKm(context);
+
         return new RiverAnnotation(this.description, data.getMainValueWAnnotations());
     }
 
+    /**
+     * Returns the current km from the context.
+     * If the context is null or doesn't contain a currentKm
+     * then a double value of -1 will be returned.
+     *
+     * @param context
+     *            The CallContext instance
+     * @return the current km as double
+     */
+    // FIXME: copied from org.dive4elements.river.artifacts.model.fixings.FixingsFacet
+    private double getCurrentKm(final CallContext context) {
+        if (context == null)
+            return Double.NaN;
+
+        final Double dkm = (Double) context.getContextValue(CURRENT_KM);
+        if (dkm == null)
+            return Double.NaN;
+
+        return dkm.doubleValue();
+    }
+
 
     /**
      * Create a deep copy of this Facet.

http://dive4elements.wald.intevation.org