changeset 9269:83ebeb620b5a

Station specific main value annotations in S-Info flood duration curve, corrected infrastructure flood duration calculation
author mschaefer
date Thu, 19 Jul 2018 08:07:03 +0200
parents ae9dee74e43e
children 7337034eb5d5
files artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/DurationWaterlevel.java 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/FloodDurationMainValuesQFacet.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java
diffstat 8 files changed, 175 insertions(+), 264 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/DurationWaterlevel.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/DurationWaterlevel.java	Thu Jul 19 08:07:03 2018 +0200
@@ -36,6 +36,10 @@
         return this.w;
     }
 
+    public double getDischarge() {
+        return this.q;
+    }
+
     public int getFloodDurDaysPerYear() {
         return this.floodDurDaysPerYear;
     }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java	Thu Jul 19 08:07:03 2018 +0200
@@ -114,4 +114,26 @@
         final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, null);
         return calculator.calcInfrastructureAnnotations(problems, station, result);
     }
+
+    /**
+     * Calculates the annotations of the W main values of a station
+     */
+    public List<StickyAxisAnnotation> calcMainValueWAnnotations(final double station, final FloodDurationCalculationResult result) {
+
+        final Calculation problems = new Calculation();
+
+        final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, null);
+        return calculator.calcMainValueWAnnotations(problems, station, result);
+    }
+
+    /**
+     * Calculates the annotations of the Q main values of a station
+     */
+    public List<StickyAxisAnnotation> calcMainValueQAnnotations(final double station, final FloodDurationCalculationResult result) {
+
+        final Calculation problems = new Calculation();
+
+        final FloodDurationCalculator calculator = new FloodDurationCalculator(this.context, null);
+        return calculator.calcMainValueQAnnotations(problems, station, result);
+    }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java	Thu Jul 19 08:07:03 2018 +0200
@@ -9,14 +9,9 @@
  */
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
-import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
-import org.dive4elements.river.jfree.StickyAxisAnnotation;
 
 /**
  * @author Gernot Belger
@@ -27,49 +22,5 @@
 
     public FloodDurationCalculationResults(final String calcModeLabel, final String user, final RiverInfo river, final DoubleRange calcRange) {
         super(calcModeLabel, user, river, calcRange);
-        this.mainValueWAnnotations = new ArrayList<>();
-        this.mainValueQAnnotations = new ArrayList<>();
-    }
-
-    private WQDay durationCurve;
-
-    public WQDay getDurationCurve() {
-        return this.durationCurve;
-    }
-
-    public void setDurationCurve(final WQDay durationCurve) {
-        this.durationCurve = durationCurve;
-    }
-
-    private final List<StickyAxisAnnotation> mainValueWAnnotations;
-
-    public List<StickyAxisAnnotation> getMainValueWAnnotations() {
-        return this.mainValueWAnnotations;
     }
-
-    private final List<StickyAxisAnnotation> mainValueQAnnotations;
-
-    public List<StickyAxisAnnotation> getMainValueQAnnotations() {
-        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;
-    // }
 }
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Thu Jul 19 08:07:03 2018 +0200
@@ -27,11 +27,13 @@
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.artifacts.model.WQKms;
+import org.dive4elements.river.artifacts.model.WstValueTable;
+import org.dive4elements.river.artifacts.model.WstValueTable.QPosition;
+import org.dive4elements.river.artifacts.model.WstValueTableFactory;
 import org.dive4elements.river.artifacts.resources.Resources;
 import org.dive4elements.river.artifacts.sinfo.common.GaugeDurationValuesFinder;
 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
-import org.dive4elements.river.artifacts.sinfo.common.WQBaseTableFinder;
 import org.dive4elements.river.artifacts.sinfo.flood_duration.RiversideRadioChoice.RiversideChoiceKey;
 import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
 import org.dive4elements.river.jfree.StickyAxisAnnotation;
@@ -90,40 +92,52 @@
         final double[] stationsSorted = sortStations(allStations.keySet());
 
         // Calculate W and Q for all stations and the selected discharge states
-        // TODO Laut Herrn Reiß: Q und D jeweils konstant für jedes Pegel-Intervall, Q-Änderungen (Zuflüsse etc.) aus .wst
-        // ignorieren
+        // TODO Geht das schneller, wenn man WstValueTable statt WINFOArtifact.computeWaterlevelData nutzt?
         final WQKms[] wqkmsArray = calculateWaterlevels(winfo, stationsSorted, problems);
 
         // Determine discharge state labels of the main values
         updateMainValueLabels(wqkmsArray, winfo, problems);
 
-        // Create a finder for Q in the {river}.wst km-w-q table
-        final WQBaseTableFinder wqFinder = WQBaseTableFinder.loadValues(this.riverInfoProvider.getRiver(), calcRange.getMinimumDouble(),
-                calcRange.getMaximumDouble(), problems);
+        // Load base wst table (river).wst - first run takes long time, then it's cached
+        final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
 
         // Calculate the durations and create the result rows
         for (int i = 0; i <= stationsSorted.length - 1; i++) {
             final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true);
             final ResultRow row = createRow(stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i);
             if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
-                calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wqFinder, durFinders);
+                calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wst, durFinders);
             this.rows.add(row);
             if (secondBank.containsKey(stationsSorted[i])) {
                 final ResultRow row2 = ResultRow.create(row);
-                calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wqFinder, durFinders);
+                calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wst, durFinders);
                 this.rows.add(row2);
             }
         }
+
+        //// Create a finder for Q in the {river}.wst km-w-q table
+        // final WQBaseTableFinder wqFinder = WQBaseTableFinder.loadValues(this.riverInfoProvider.getRiver(),
+        //// calcRange.getMinimumDouble(),
+        // calcRange.getMaximumDouble(), problems);
+        //
+        //// Calculate the durations and create the result rows
+        // for (int i = 0; i <= stationsSorted.length - 1; i++) {
+        // final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true);
+        // final ResultRow row = createRow(stationsSorted[i], gauge, firstGauge, wqkmsArray, durFinders.get(gauge), i);
+        // if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
+        // calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wqFinder, durFinders);
+        // this.rows.add(row);
+        // if (secondBank.containsKey(stationsSorted[i])) {
+        // final ResultRow row2 = ResultRow.create(row);
+        // calculateInfrastructure(row2, gauge, secondBank.get(stationsSorted[i]), wqFinder, durFinders);
+        // this.rows.add(row2);
+        // }
+        // }
+
         final String[] mainValueLabels = new String[wqkmsArray.length];
         for (int i = 0; i <= wqkmsArray.length - 1; i++)
             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);
     }
 
     /**
@@ -148,30 +162,63 @@
     }
 
     /**
-     * Calculate the data for the W and Q main value lines in the duration curve chart and add to result collection
+     * Calculates the data for the Q main value lines in the duration curve chart
      */
-    public void calcMainValueAnnotations(final Calculation problems, final int stationIndex, final AttributeKey riverside,
-            final WQKms[] wqkmsArray, final FloodDurationCalculationResults results) {
+    public List<StickyAxisAnnotation> calcMainValueQAnnotations(final Calculation problems, final double station, final FloodDurationCalculationResult result) {
 
-        // Same way as in MainValueWFacet and ..QFacet, but special label handling
-        final List<StickyAxisAnnotation> ws = new ArrayList<>();
-        final List<StickyAxisAnnotation> qs = new ArrayList<>();
-        for (int i = 0; i <= wqkmsArray.length - 1; i++) {
-            final String qLabel = wqkmsArray[i].getName().startsWith("W=") ? "Q(" + wqkmsArray[i].getName() + ")" : wqkmsArray[i].getName();
-            final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(qLabel, (float) wqkmsArray[i].getQ(stationIndex), SimpleAxis.Y_AXIS,
+        // 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 new ArrayList<>();
+        }
+        final ResultRow row = stationRows.get(0);
+        final List<StickyAxisAnnotation> annotations = new ArrayList<>();
+        final List<DurationWaterlevel> wqds = (List<DurationWaterlevel>) row.getValue(SInfoResultType.customMultiRowColWaterlevel);
+        for (final DurationWaterlevel wqd : wqds) {
+            final String label = wqd.getBezeichnung().startsWith("W=") ? "Q(" + wqd.getBezeichnung() + ")" : wqd.getBezeichnung();
+            final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) wqd.getDischarge(), SimpleAxis.Y_AXIS,
                     FloodDurationCurveGenerator.YAXIS.Q.idx);
-            qs.add(qAnnotation);
-            FloodDurationMainValuesQFacet.setHitPoint(results.getDurationCurve(), qAnnotation);
-            final String wLabel = !wqkmsArray[i].getName().startsWith("W=") ? "W(" + wqkmsArray[i].getName() + ")" : wqkmsArray[i].getName();
-            final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(wLabel, (float) wqkmsArray[i].getW(stationIndex), SimpleAxis.Y_AXIS,
+            annotation.setHitPoint(wqd.getFloodDurDaysPerYear());
+            annotations.add(annotation);
+        }
+        return annotations;
+    }
+
+    /**
+     * Calculates the data for the W main value lines in the duration curve chart
+     */
+    public List<StickyAxisAnnotation> calcMainValueWAnnotations(final Calculation problems, final double station, final FloodDurationCalculationResult result) {
+
+        // 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 new ArrayList<>();
+        }
+        final List<StickyAxisAnnotation> annotations = new ArrayList<>();
+        final ResultRow row = stationRows.get(0);
+        final List<DurationWaterlevel> wqds = (List<DurationWaterlevel>) row.getValue(SInfoResultType.customMultiRowColWaterlevel);
+        for (final DurationWaterlevel wqd : wqds) {
+            final String label = !wqd.getBezeichnung().startsWith("W=") ? "W(" + wqd.getBezeichnung() + ")" : wqd.getBezeichnung();
+            final StickyAxisAnnotation annotation = new StickyAxisAnnotation(label, (float) wqd.getWaterlevel(), SimpleAxis.Y_AXIS,
                     FloodDurationCurveGenerator.YAXIS.W.idx);
-            ws.add(wAnnotation);
-            FloodDurationMainValuesWFacet.setHitPoint(results.getDurationCurve(), wAnnotation);
+            annotation.setHitPoint(wqd.getFloodDurDaysPerYear());
+            annotations.add(annotation);
         }
-        results.getMainValueQAnnotations().clear();
-        results.getMainValueQAnnotations().addAll(qs);
-        results.getMainValueWAnnotations().clear();
-        results.getMainValueWAnnotations().addAll(ws);
+        return annotations;
     }
 
     /**
@@ -191,13 +238,13 @@
         }
         final List<ResultRow> stationRows = searchStation(station1, result.getRows());
         if (stationRows.isEmpty() || (stationRows.get(0).getValue(SInfoResultType.infrastructuretype) == null)) {
-            return null;
+            return new ArrayList<>();
         }
         // 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));
+            annotations.add(calcInfrastructureWAnnotation(row));
+            annotations.add(calcInfrastructureQAnnotation(row));
         }
         return annotations;
     }
@@ -219,7 +266,7 @@
     /**
      * Calculates the Q annotation lines of an infrastructure
      */
-    private StickyAxisAnnotation calcQAnnotation(final ResultRow row) {
+    private StickyAxisAnnotation calcInfrastructureQAnnotation(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))
@@ -233,7 +280,7 @@
     /**
      * Calculates the W annotation lines of an infrastructure
      */
-    private StickyAxisAnnotation calcWAnnotation(final ResultRow row) {
+    private StickyAxisAnnotation calcInfrastructureWAnnotation(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))
@@ -378,15 +425,43 @@
         return row;
     }
 
+    /// **
+    // * Calculate the result row fields for one infrastructure - gives wrong duration numbers where Q changes within the
+    /// gauge range
+    // */
+    // private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue
+    /// infrastructure, final WQBaseTableFinder wqFinder,
+    // final Map<Gauge, GaugeDurationValuesFinder> durFinders) {
+    //
+    // final double q = wqFinder.getDischarge(infrastructure.getStation(), infrastructure.getHeight());
+    // final double qOut = Double.isInfinite(q) ? Double.NaN : q;
+    // final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(q));
+    // row.putValue(SInfoResultType.riverside, infrastructure.getAttributeKey());
+    // row.putValue(SInfoResultType.floodDuration, dur);
+    // row.putValue(SInfoResultType.floodDischarge, qOut);
+    // row.putValue(SInfoResultType.infrastructureHeight, infrastructure.getHeight());
+    // row.putValue(SInfoResultType.infrastructuretype, infrastructure.getInfrastructure().getType().getName());
+    // }
+
     /**
      * Calculate the result row fields for one infrastructure
      */
-    private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue infrastructure, final WQBaseTableFinder wqFinder,
+    private void calculateInfrastructure(final ResultRow row, final Gauge gauge, final InfrastructureValue infrastructure, final WstValueTable wst,
             final Map<Gauge, GaugeDurationValuesFinder> durFinders) {
 
-        final double q = wqFinder.getDischarge(infrastructure.getStation(), infrastructure.getHeight());
+        // Interpolate the infrastructure height in the wst table to get the corresponding Q
+        final Calculation problems = new Calculation();
+        final double[] qs = wst.findQsForW(infrastructure.getStation().doubleValue(), infrastructure.getHeight().doubleValue(), problems);
+        // TODO Fehlerbehandlung (kein Q gefunden)
+        final double q = (qs.length >= 1) ? qs[0] : Double.NaN;
         final double qOut = Double.isInfinite(q) ? Double.NaN : q;
-        final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(q));
+        // Determine the relative column position of the Q
+        final QPosition qPos = wst.getQPosition(infrastructure.getStation().doubleValue(), q);
+        // Get the Q for the found column position for the station of the gauge
+        final double qGauge = wst.getQ(qPos, gauge.getStation().doubleValue());
+        // Interpolate the Q-D-table of the gauge
+        final double dur = underflowDaysToOverflowDays(durFinders.get(gauge).getDuration(qGauge));
+        // Set result row
         row.putValue(SInfoResultType.riverside, infrastructure.getAttributeKey());
         row.putValue(SInfoResultType.floodDuration, dur);
         row.putValue(SInfoResultType.floodDischarge, qOut);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java	Thu Jul 19 08:07:03 2018 +0200
@@ -1,5 +1,7 @@
-/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
- * Software engineering by Intevation GmbH
+/** 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
@@ -19,7 +21,7 @@
 
 
 /**
- * Data of a duration curve.
+ * Data of a flood duration curve.
  */
 public class FloodDurationCurveFacet extends DefaultFacet {
 
@@ -27,12 +29,6 @@
 
     private static Logger log = Logger.getLogger(FloodDurationCurveFacet.class);
 
-    // /** Blackboard data provider key for durationcurve (wqday) data. */
-    // public static String BB_DURATIONCURVE = "durationcurve";
-    //
-    // /** Blackboard data provider key for km of durationcurve. */
-    // public static String BB_DURATIONCURVE_KM = "durationcurve.km";
-
     public FloodDurationCurveFacet() {
     }
 
@@ -51,60 +47,10 @@
 
         final D4EArtifact flys = (D4EArtifact) artifact;
 
-        // TODO: wird das hier noch benötigt?
-        //        final CalculationResult res = (CalculationResult) flys.compute(context, ComputeType.ADVANCE, false);
-        //        final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
-
         final double currentKm = FixChartGenerator.getCurrentKm(context);
         return new FloodDurationCalculation(context).calcStationCurve(currentKm, (SINFOArtifact) flys);
     }
 
-    // private WQDay getTestData() {
-    // final int[] days = new int[366];
-    // final double[] ws = new double[366];
-    // final double[] qs = new double[366];
-    // for (int i = 0; i <= 365; i++) {
-    // days[i] = i;
-    // final double x = (i - 182.5) / 182.5;
-    // ws[i] = 102.0 - (Math.pow(x, 5) + x);
-    // qs[i] = 1600.0 - 800 * (Math.pow(x, 9) + x);
-    // }
-    // return new WQDay(days, ws, qs);
-    // }
-
-    // @Override
-    // public List getStaticDataProviderKeys(final Artifact art) {
-    // final List list = new ArrayList();
-    // list.add(BB_DURATIONCURVE);
-    // list.add(BB_DURATIONCURVE_KM);
-    // return list;
-    // }
-
-
-    // /**
-    // * Can provide whatever getData returns and additionally the location.
-    // * @param key will respond on BB_DURATIONCURVE +KM
-    // * @param param ignored
-    // * @param context ignored
-    // * @return whatever getData delivers or location.
-    // */
-    // @Override
-    // public Object provideBlackboardData(final Artifact artifact,
-    // final Object key,
-    // final Object param,
-    // final CallContext context
-    // ) {
-    // if (key.equals(BB_DURATIONCURVE)) {
-    // return getData(artifact, context);
-    // }
-    // else if (key.equals(BB_DURATIONCURVE_KM)) {
-    // return ((D4EArtifact)artifact).getDataAsString("ld_locations");
-    // }
-    // else {
-    // return null;
-    // }
-    // }
-
 
     /** Create a deep copy. */
     @Override
@@ -114,4 +60,4 @@
         return copy;
     }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationInfrastructureFacet.java	Thu Jul 19 08:07:03 2018 +0200
@@ -10,8 +10,6 @@
 
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
-import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
-
 import java.util.List;
 
 import org.apache.log4j.Logger;
@@ -21,6 +19,7 @@
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.fixings.FixChartGenerator;
 import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.jfree.StickyAxisAnnotation;
 
@@ -43,12 +42,6 @@
 
     /**
      * Returns the data this facet requires.
-     *
-     * @param artifact the owner artifact.
-     * @param context  the CallContext (can be used to find out if in
-     *                 navigable fixation-setting, or durationcurve).
-     *
-     * @return the data.
      */
     @Override
     public Object getData(final Artifact artifact, final CallContext context) {
@@ -61,40 +54,12 @@
 
         final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
 
-        // final List<StickyAxisAnnotation> annotations = new ArrayList<>();
-        // annotations.add(data.getInfrastructureWAnnotation());
-        // annotations.add(data.getInfrastructureQAnnotation());
-
-        final double currentKm = getCurrentKm(context);
+        final double currentKm = FixChartGenerator.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();
+        return new RiverAnnotation(this.description, annotations);
     }
 
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesQFacet.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesQFacet.java	Thu Jul 19 08:07:03 2018 +0200
@@ -1,5 +1,7 @@
-/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
- * Software engineering by Intevation GmbH
+/** 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
@@ -8,14 +10,16 @@
 
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
+import java.util.List;
+
 import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.state.DefaultFacet;
 import org.dive4elements.artifacts.Artifact;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.fixings.FixChartGenerator;
 import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.jfree.StickyAxisAnnotation;
 
@@ -35,30 +39,9 @@
         this.index = 1;
     }
 
-    /**
-     * Set the hit-point in Q where a line drawn from the axis would hit the
-     * curve in WQDay (if hit).
-     * Employ linear interpolation.
-     */
-    public static void setHitPoint(final WQDay wqday, final StickyAxisAnnotation annotation) {
-
-        final float q = annotation.getPos();
-        final Double day = wqday.interpolateDayByQ(q);
-        if (day != null)
-            annotation.setHitPoint(day.floatValue());
-        else
-            log.debug("StickyAnnotation does not hit wqday curve: " + q);
-    }
-
 
     /**
      * Returns the data this facet requires.
-     *
-     * @param artifact the owner artifact.
-     * @param context  the CallContext (can be used to find out if in
-     *                 navigable fixation-setting, or durationcurve).
-     *
-     * @return the data.
      */
     @Override
     public Object getData(final Artifact artifact, final CallContext context) {
@@ -71,7 +54,12 @@
 
         final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
 
-        return new RiverAnnotation(this.description, data.getMainValueQAnnotations());
+        final double currentKm = FixChartGenerator.getCurrentKm(context);
+
+        final List<StickyAxisAnnotation> annotations = new FloodDurationCalculation(context).calcMainValueQAnnotations(currentKm,
+                data.getResults().get(0));
+
+        return new RiverAnnotation(this.description, annotations);
     }
 
 
@@ -86,4 +74,3 @@
         return copy;
     }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java	Wed Jul 18 18:53:15 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationMainValuesWFacet.java	Thu Jul 19 08:07:03 2018 +0200
@@ -1,5 +1,7 @@
-/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
- * Software engineering by Intevation GmbH
+/** 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
@@ -8,7 +10,7 @@
 
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
-import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
+import java.util.List;
 
 import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.state.DefaultFacet;
@@ -16,8 +18,8 @@
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.D4EArtifact;
 import org.dive4elements.river.artifacts.model.CalculationResult;
-import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.artifacts.states.DefaultState.ComputeType;
+import org.dive4elements.river.exports.fixings.FixChartGenerator;
 import org.dive4elements.river.jfree.RiverAnnotation;
 import org.dive4elements.river.jfree.StickyAxisAnnotation;
 
@@ -36,31 +38,8 @@
         this.index = 0;
     }
 
-
-    /**
-     * Set the hit-point in W where a line drawn from the axis would hit the
-     * curve in WQDay (if hit).
-     * Employ linear interpolation.
-     */
-    public static void setHitPoint(final WQDay wqday, final StickyAxisAnnotation annotation) {
-
-        final float w = annotation.getPos();
-        final Double day = wqday.interpolateDayByW(w);
-        if (day != null)
-            annotation.setHitPoint(day.floatValue());
-        else
-            log.debug("StickyAnnotation does not hit wqday curve: " + w);
-    }
-
-
     /**
      * Returns the data this facet provides.
-     *
-     * @param artifact the owner artifact.
-     * @param context  the CallContext (can be used to find out if in
-     *                 navigable fixation-setting, or durationcurve).
-     *
-     * @return the data.
      */
     @Override
     public Object getData(final Artifact artifact, final CallContext context) {
@@ -73,30 +52,12 @@
 
         final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
 
-        final double currentKm = getCurrentKm(context);
-
-        return new RiverAnnotation(this.description, data.getMainValueWAnnotations());
-    }
+        final double currentKm = FixChartGenerator.getCurrentKm(context);
 
-    /**
-     * 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 List<StickyAxisAnnotation> annotations = new FloodDurationCalculation(context).calcMainValueWAnnotations(currentKm,
+                data.getResults().get(0));
 
-        final Double dkm = (Double) context.getContextValue(CURRENT_KM);
-        if (dkm == null)
-            return Double.NaN;
-
-        return dkm.doubleValue();
+        return new RiverAnnotation(this.description, annotations);
     }
 
 
@@ -111,4 +72,4 @@
         return copy;
     }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+

http://dive4elements.wald.intevation.org