changeset 9265:e5367900dd6d

Small cleanup concerning getPoints Adding validStations as dataItem to flood duration calculation Flood duration now km aware
author gernotbelger
date Tue, 17 Jul 2018 19:48:28 +0200
parents baef46792354
children 465347d12990
files artifacts/doc/conf/artifacts/sinfo.xml artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractCalculationResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.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/FloodDurationCurveGenerator.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationProcessor.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationState.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodHeightProcessor.java
diffstat 11 files changed, 140 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/doc/conf/artifacts/sinfo.xml	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/doc/conf/artifacts/sinfo.xml	Tue Jul 17 19:48:28 2018 +0200
@@ -25,6 +25,12 @@
     <state id="state.sinfo.distance_only" description="state.sinfo.distance_only" state="org.dive4elements.river.artifacts.states.DistanceOnlySelect" helpText="help.state.sinfo.distance_only">
       <data name="ld_from" type="Double" />
       <data name="ld_to" type="Double" />
+
+      <!-- This data will hold the valid stations, needed for the Duration-Chart for the flood duration calculation
+            It is ugly to put it here, but we cannot set the state-data of the current state inside the state calculation (only the data of the previous states is put into the collection description).
+            So this is the only way to safely transport this information to the client.
+       -->    
+      <data name="validStations" type="String" />
     </state>
 
     <transition transition="org.dive4elements.river.artifacts.transitions.ValueCompareTransition">
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractCalculationResult.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/common/AbstractCalculationResult.java	Tue Jul 17 19:48:28 2018 +0200
@@ -15,6 +15,9 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.commons.collections.Predicate;
+import org.apache.commons.collections.functors.TruePredicate;
+
 import gnu.trove.TDoubleArrayList;
 
 /**
@@ -24,7 +27,7 @@
 
     private static final long serialVersionUID = 1L;
 
-    protected final Collection<ResultRow> rows;
+    private final Collection<ResultRow> rows;
 
     private final String label;
 
@@ -45,18 +48,24 @@
         return Collections.unmodifiableCollection(this.rows);
     }
 
-    public final double[][] getStationPoints(final IResultType type) { // gehört die Methode hier rein? oder in erbende Klassen?
+    public final double[][] getStationPoints(final IResultType yType) {
+        return getPoints(GeneralResultType.station, yType, TruePredicate.INSTANCE);
+    }
+
+    public final double[][] getPoints(final IResultType typeX, final IResultType typeY, final Predicate rowFilter) {
 
         final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
         final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
 
         for (final ResultRow row : this.rows) {
 
-            final double station = row.getDoubleValue(GeneralResultType.station); // TODO: move "station" (and others) to common
-            final double value = row.getDoubleValue(type);
+            if (rowFilter.evaluate(row)) {
+                final double station = row.getDoubleValue(typeX);
+                final double value = row.getDoubleValue(typeY);
 
-            xPoints.add(station);
-            yPoints.add(value);
+                xPoints.add(station);
+                yPoints.add(value);
+            }
         }
 
         return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/collision/CollisionCalcOverviewResult.java	Tue Jul 17 19:48:28 2018 +0200
@@ -12,6 +12,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 
+import org.apache.commons.collections.Predicate;
 import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
 import org.dive4elements.river.artifacts.common.ExportContextCSV;
 import org.dive4elements.river.artifacts.common.ExportContextPDF;
@@ -22,8 +23,6 @@
 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
 
-import gnu.trove.TDoubleArrayList;
-
 /**
  * Contains the results of a {@link CollisionCalculation}.
  *
@@ -48,22 +47,15 @@
 
     public double[][] getStationPointsByYear(final IResultType type, final int year) {
 
-        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
-        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
-
-        for (final ResultRow row : this.rows) {
-
-            if ((this.singleYears == null) || (Integer.valueOf(row.getValue(SInfoResultType.years).toString()) == year)) {
+        final Predicate filter = new Predicate() {
+            @Override
+            public boolean evaluate(final Object object) {
+                final ResultRow row = (ResultRow) object;
+                return getSingleYears() == null || Integer.valueOf(row.getValue(SInfoResultType.years).toString()) == year;
+            }
+        };
 
-                final double station = row.getDoubleValue(GeneralResultType.station);
-                final double value = row.getDoubleValue(type);
-
-                xPoints.add(station);
-                yPoints.add(value);
-            }
-        }
-
-        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
+        return getPoints(GeneralResultType.station, type, filter);
     }
 
     @Override
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResult.java	Tue Jul 17 19:48:28 2018 +0200
@@ -15,6 +15,7 @@
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.commons.collections.Predicate;
 import org.dive4elements.river.artifacts.common.AbstractCalculationExportableResult;
 import org.dive4elements.river.artifacts.common.AbstractExportContext;
 import org.dive4elements.river.artifacts.common.ExportContextCSV;
@@ -26,7 +27,6 @@
 import org.dive4elements.river.artifacts.sinfo.common.SInfoI18NStrings;
 import org.dive4elements.river.artifacts.sinfo.common.SInfoResultType;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
-import org.dive4elements.river.exports.DiagramGenerator;
 import org.dive4elements.river.model.Attribute.AttributeKey;
 
 import gnu.trove.TDoubleArrayList;
@@ -38,6 +38,22 @@
  */
 public final class FloodDurationCalculationResult extends AbstractCalculationExportableResult {
 
+    private final static class RiversidePredicate implements Predicate {
+
+        private final AttributeKey riverside;
+
+        public RiversidePredicate(final AttributeKey riverside) {
+            this.riverside = riverside;
+        }
+
+        @Override
+        public boolean evaluate(final Object object) {
+            final ResultRow row = (ResultRow) object;
+
+            return row.getValue(SInfoResultType.riverside) == this.riverside;
+        }
+    }
+
     private static final long serialVersionUID = 1L;
 
     private final String[] mainvalueLabels;
@@ -62,12 +78,17 @@
     /**
      * Collection of the result rows containing only the rows describing an infrastructure
      */
+    // FIXME: bad to override, instead make new method 'getInfrastructureRows' or similar?
     @Override
     public Collection<ResultRow> getRows() {
+
+        final Collection<ResultRow> rows = super.getRows();
+
         final List<ResultRow> infrasOnlyRows = new ArrayList<>();
-        for (final ResultRow row : this.rows)
+        for (final ResultRow row : rows) {
             if (row.getValue(SInfoResultType.infrastructuretype) != null)
                 infrasOnlyRows.add(row);
+        }
         return Collections.unmodifiableCollection(infrasOnlyRows);
     }
 
@@ -82,7 +103,7 @@
                 exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_NAME, String.format("%d: %s", i, label));
             }
             // "# Bezugspegel: "
-            for (final ResultRow row : this.rows) {
+            for (final ResultRow row : getRows()) {
                 exportContextCSV.writeCSVMetaEntry(SInfoI18NStrings.CSV_META_HEADER_WATERLEVEL_GAUGE, row.getValue(SInfoResultType.gaugeLabel));
                 break;
             }
@@ -94,8 +115,8 @@
     protected String getJasperFile() {
         if (this.getWaterlevelCount() <= 1)
             return "/jasper/templates/sinfo.floodduration.jrxml";
-        else
-            return "/jasper/templates/sinfo.floodduration2.jrxml";
+
+        return "/jasper/templates/sinfo.floodduration2.jrxml";
     }
 
     protected String[] formatRow(final AbstractExportContext exportContextCSV, final ResultRow row, final ExportMode mode) {
@@ -160,7 +181,10 @@
         header.add(exportContextCSV.formatCsvHeader(SInfoResultType.location));
 
         exportContextCSV.writeCSVLine(header.toArray(new String[header.size()]));
+    }
 
+    public List<Double> getValidDurationChartKilometers() {
+        return getValues(GeneralResultType.station);
     }
 
     @Override
@@ -221,32 +245,20 @@
      * Gets the longitudinal section of a result value type for one river side
      */
     public final double[][] getInfrastructurePoints(final IResultType type, final AttributeKey riverside) {
-
-        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
-        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
-
-        for (final ResultRow row : this.rows) {
-
-            final double station = row.getDoubleValue(GeneralResultType.station);
-            final double value = row.getDoubleValue(type);
-            if (row.getValue(SInfoResultType.riverside) == riverside) {
-                xPoints.add(station);
-                yPoints.add(value);
-            }
-        }
-
-        return new double[][] { xPoints.toNativeArray(), yPoints.toNativeArray() };
+        return getPoints(GeneralResultType.station, type, new RiversidePredicate(riverside));
     }
 
     /**
      * Gets a longitudinal section of W, Q, or flood duration of one of the waterlevels
      */
-    public final double[][] getMainValueDurationPoints(final DiagramGenerator generator, final ValueGetter valuegetter, final int dataIndex) {
+    public final double[][] getMainValueDurationPoints(final ValueGetter valuegetter, final int dataIndex) {
 
-        final TDoubleArrayList xPoints = new TDoubleArrayList(this.rows.size());
-        final TDoubleArrayList yPoints = new TDoubleArrayList(this.rows.size());
+        final Collection<ResultRow> rows = getRows();
 
-        for (final ResultRow row : this.rows) {
+        final TDoubleArrayList xPoints = new TDoubleArrayList(rows.size());
+        final TDoubleArrayList yPoints = new TDoubleArrayList(rows.size());
+
+        for (final ResultRow row : rows) {
 
             final double station = row.getDoubleValue(GeneralResultType.station);
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculationResults.java	Tue Jul 17 19:48:28 2018 +0200
@@ -14,7 +14,7 @@
 
 import org.apache.commons.lang.math.DoubleRange;
 import org.dive4elements.river.artifacts.common.AbstractCalculationResults;
-import org.dive4elements.river.artifacts.model.CalculationResult;
+import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
 import org.dive4elements.river.jfree.StickyAxisAnnotation;
 
@@ -31,13 +31,13 @@
         this.mainValueQAnnotations = new ArrayList<>();
     }
 
-    private CalculationResult durationCurve;
+    private WQDay durationCurve;
 
-    public CalculationResult getDurationCurve() {
+    public WQDay getDurationCurve() {
         return this.durationCurve;
     }
 
-    public void setDurationCurve(final CalculationResult durationCurve) {
+    public void setDurationCurve(final WQDay durationCurve) {
         this.durationCurve = durationCurve;
     }
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Tue Jul 17 19:48:28 2018 +0200
@@ -144,8 +144,7 @@
             ws[j] = underflow.getW(i);
             qs[j] = underflow.getQ(i);
         }
-        res.setData(new WQDay(days, ws, qs));
-        results.setDurationCurve(res);
+        results.setDurationCurve(new WQDay(days, ws, qs));
     }
 
     /**
@@ -162,12 +161,12 @@
             final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(qLabel, (float) wqkmsArray[i].getQ(stationIndex), SimpleAxis.Y_AXIS,
                     FloodDurationCurveGenerator.YAXIS.Q.idx);
             qs.add(qAnnotation);
-            FloodDurationMainValuesQFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), 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,
                     FloodDurationCurveGenerator.YAXIS.W.idx);
             ws.add(wAnnotation);
-            FloodDurationMainValuesWFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), wAnnotation);
+            FloodDurationMainValuesWFacet.setHitPoint(results.getDurationCurve(), wAnnotation);
         }
         results.getMainValueQAnnotations().clear();
         results.getMainValueQAnnotations().addAll(qs);
@@ -194,10 +193,10 @@
                 + ", " + SInfoResultType.riverside.exportValue(this.context, row.getValue(SInfoResultType.riverside)));
         final StickyAxisAnnotation qAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.floodDischarge),
                 SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.Q.idx);
-        FloodDurationMainValuesQFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), qAnnotation);
+        FloodDurationMainValuesQFacet.setHitPoint(results.getDurationCurve(), qAnnotation);
         final StickyAxisAnnotation wAnnotation = new StickyAxisAnnotation(label, (float) row.getDoubleValue(SInfoResultType.infrastructureHeight),
                 SimpleAxis.Y_AXIS, FloodDurationCurveGenerator.YAXIS.W.idx);
-        FloodDurationMainValuesWFacet.setHitPoint((WQDay) results.getDurationCurve().getData(), wAnnotation);
+        FloodDurationMainValuesWFacet.setHitPoint(results.getDurationCurve(), wAnnotation);
 
         results.setInfrastructureQAnnotation(qAnnotation);
         results.setInfrastructureWAnnotation(wAnnotation);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveFacet.java	Tue Jul 17 19:48:28 2018 +0200
@@ -8,8 +8,7 @@
 
 package org.dive4elements.river.artifacts.sinfo.flood_duration;
 
-//import java.util.ArrayList;
-//import java.util.List;
+import static org.dive4elements.river.exports.injector.InjectorConstants.CURRENT_KM;
 
 import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.state.DefaultFacet;
@@ -18,7 +17,6 @@
 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;
 
 
@@ -57,8 +55,32 @@
 
         final FloodDurationCalculationResults data = (FloodDurationCalculationResults) res.getData();
 
+        final double currentKm = getCurrentKm(context);
+        // TODO: entweder in data.getDurationCurve() reingeben, oder bei FloodDurationCalculationResults auswerten...
+        // TODO: was ist aus perfromanz/speicher-sicht besser?
+
         return data.getDurationCurve();
-        // return getTestData();
+    }
+
+    /**
+     * 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();
     }
 
     // private WQDay getTestData() {
@@ -74,7 +96,6 @@
     // return new WQDay(days, ws, qs);
     // }
 
-
     // @Override
     // public List getStaticDataProviderKeys(final Artifact art) {
     // final List list = new ArrayList();
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveGenerator.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCurveGenerator.java	Tue Jul 17 19:48:28 2018 +0200
@@ -14,7 +14,6 @@
 import org.apache.log4j.Logger;
 import org.dive4elements.artifactdatabase.state.ArtifactAndFacet;
 import org.dive4elements.artifacts.CallContext;
-import org.dive4elements.river.artifacts.model.CalculationResult;
 import org.dive4elements.river.artifacts.model.FacetTypes;
 import org.dive4elements.river.artifacts.model.WQDay;
 import org.dive4elements.river.exports.IdentifiableNumberAxis;
@@ -29,57 +28,51 @@
 import org.jfree.data.Range;
 import org.jfree.data.xy.XYSeries;
 
-
 /**
  * An OutGenerator that generates duration curves.
  *
  * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
  */
-public class FloodDurationCurveGenerator
-extends      XYChartGenerator
-implements   FacetTypes
-{
+public class FloodDurationCurveGenerator extends XYChartGenerator implements FacetTypes {
     public static enum YAXIS {
-        W(0),
-        Q(1);
+        W(0), Q(1);
         public int idx;
+
         private YAXIS(final int c) {
             this.idx = c;
         }
     }
 
     /** Local log. */
-    private static Logger log =
-            Logger.getLogger(FloodDurationCurveGenerator.class);
-
-    public static final String I18N_CHART_TITLE = "sinfo.chart.flood_duration.curve.section.title";
-
-    public static final String I18N_CHART_SUBTITLE = "chart.duration.curve.subtitle";
+    private static Logger log = Logger.getLogger(FloodDurationCurveGenerator.class);
 
-    public static final String I18N_XAXIS_LABEL = "sinfo.chart.flood_duration.curve.xaxis.label";
-
-    public static final String I18N_YAXIS_LABEL_W = "chart.duration.curve.yaxis.label.w";
+    private static final String I18N_CHART_TITLE = "sinfo.chart.flood_duration.curve.section.title";
 
-    public static final String I18N_YAXIS_LABEL_Q = "chart.duration.curve.yaxis.label.q";
+    private static final String I18N_CHART_SUBTITLE = "chart.duration.curve.subtitle";
 
-    public static final String I18N_CHART_TITLE_DEFAULT = "Dauerlinie";
+    private static final String I18N_XAXIS_LABEL = "sinfo.chart.flood_duration.curve.xaxis.label";
 
-    public static final String I18N_XAXIS_LABEL_DEFAULT = "Überflutungsdauer [d/a]";
+    private static final String I18N_YAXIS_LABEL_W = "chart.duration.curve.yaxis.label.w";
 
+    private static final String I18N_YAXIS_LABEL_Q = "chart.duration.curve.yaxis.label.q";
+
+    private static final String I18N_CHART_TITLE_DEFAULT = "Dauerlinie";
+
+    private static final String I18N_XAXIS_LABEL_DEFAULT = "Überflutungsdauer [d/a]";
 
     public FloodDurationCurveGenerator() {
         super();
     }
 
-
     /**
      * Create Axis for given index.
+     *
      * @return axis with according internationalized label.
      */
     @Override
     protected NumberAxis createYAxis(final int index) {
         final Font labelFont = new Font("Tahoma", Font.BOLD, 14);
-        final String label   = getYAxisLabel(index);
+        final String label = getYAxisLabel(index);
 
         final NumberAxis axis = createNumberAxis(index, label);
         if (index == YAXIS.W.idx) {
@@ -89,41 +82,35 @@
         return axis;
     }
 
-
     @Override
     protected String getDefaultChartTitle(final CallContext context) {
         return msg(I18N_CHART_TITLE, I18N_CHART_TITLE_DEFAULT);
     }
 
-
     @Override
     protected String getDefaultChartSubtitle(final CallContext context) {
 
-        final double[] dist  = getRange();
+        final double[] dist = getRange();
         return msg(I18N_CHART_SUBTITLE, "", getRiverName(), dist[0]);
     }
 
-
     @Override
     protected String getDefaultXAxisLabel(final CallContext context) {
         return msg(I18N_XAXIS_LABEL, I18N_XAXIS_LABEL_DEFAULT);
     }
 
-
     @Override
     protected String getDefaultYAxisLabel(final int index) {
 
         String label = "default";
         if (index == YAXIS.W.idx) {
             label = msg(I18N_YAXIS_LABEL_W, I18N_YAXIS_LABEL_W, getRiverUnit());
-        }
-        else if (index == YAXIS.Q.idx) {
+        } else if (index == YAXIS.Q.idx) {
             label = msg(I18N_YAXIS_LABEL_Q);
         }
         return label;
     }
 
-
     @Override
     protected boolean zoomX(final XYPlot plot, final ValueAxis axis, final Bounds bounds, final Range x) {
 
@@ -134,7 +121,6 @@
         return zoomin;
     }
 
-
     /**
      * This method overrides the method in the parent class to set the lower
      * bounds of the Q axis to 0. This axis should never display negative
@@ -152,7 +138,6 @@
         return zoomin;
     }
 
-
     @Override
     public void doOut(final ArtifactAndFacet artifactFacet, final ThemeDocument attr, final boolean visible) {
 
@@ -168,10 +153,10 @@
         final CallContext context = getContext();
 
         if (name.equals(DURATION_W)) {
-            doWOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible);
+            doWOut((WQDay) (artifactFacet.getData(context)), artifactFacet, attr, visible);
         }
         else if (name.equals(DURATION_Q)) {
-            doQOut((WQDay) ((CalculationResult) artifactFacet.getData(context)).getData(), artifactFacet, attr, visible);
+            doQOut((WQDay) artifactFacet.getData(context), artifactFacet, attr, visible);
         }
         else if (name.equals(FloodDurationCurveProcessor.FACET_FLOOD_DURATION_MAINVALUES_Q)
                 || name.equals(FloodDurationCurveProcessor.FACET_FLOOD_DURATION_MAINVALUES_W)) {
@@ -195,7 +180,8 @@
     /**
      * Creates the series for a duration curve's W facet.
      *
-     * @param wqdays The WQDay store that contains the Ws.
+     * @param wqdays
+     *            The WQDay store that contains the Ws.
      * @param theme
      */
     protected void doWOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) {
@@ -204,7 +190,7 @@
         final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
         final int size = wqdays.size();
         for (int i = 0; i < size; i++) {
-            final int  day = wqdays.getDay(i);
+            final int day = wqdays.getDay(i);
             final double w = wqdays.getW(i);
             series.add(day, w);
         }
@@ -219,11 +205,11 @@
         addAxisSeries(series, YAXIS.W.idx, visible);
     }
 
-
     /**
      * Creates the series for a duration curve's Q facet.
      *
-     * @param wqdays The WQDay store that contains the Qs.
+     * @param wqdays
+     *            The WQDay store that contains the Qs.
      * @param theme
      */
     protected void doQOut(final WQDay wqdays, final ArtifactAndFacet aaf, final ThemeDocument theme, final boolean visible) {
@@ -232,14 +218,13 @@
         final XYSeries series = new StyledXYSeries(aaf.getFacetDescription(), theme);
         final int size = wqdays.size();
         for (int i = 0; i < size; i++) {
-            final int  day = wqdays.getDay(i);
+            final int day = wqdays.getDay(i);
             final double q = wqdays.getQ(i);
             series.add(day, q);
         }
         addAxisSeries(series, YAXIS.Q.idx, visible);
     }
 
-
     @Override
     protected YAxisWalker getYAxisWalker() {
         return new YAxisWalker() {
@@ -258,5 +243,4 @@
 
     // MainValue-Annotations should be visualized by
     // a line that goes to the curve itself.
-}
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationProcessor.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationProcessor.java	Tue Jul 17 19:48:28 2018 +0200
@@ -110,7 +110,7 @@
                         return waterlevel.getFloodDurDaysPerYear();
                     }
                 };
-                final double[][] points = ((FloodDurationCalculationResult) data).getMainValueDurationPoints(generator, valuegetter, index);
+                final double[][] points = ((FloodDurationCalculationResult) data).getMainValueDurationPoints(valuegetter, index);
                 return buildStepLineSeriesForType(points, generator, bundle, theme, visible);
             }
         }
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationState.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationState.java	Tue Jul 17 19:48:28 2018 +0200
@@ -12,6 +12,7 @@
 
 import java.util.List;
 
+import org.apache.commons.lang.StringUtils;
 import org.dive4elements.artifactdatabase.state.Facet;
 import org.dive4elements.artifacts.CallContext;
 import org.dive4elements.river.artifacts.ChartArtifact;
@@ -32,9 +33,6 @@
  */
 public class FloodDurationState extends DefaultState {
 
-    /// ** The log that is used in this state. */
-    // private static Logger log = Logger.getLogger(FloodDurationState.class);
-
     private static final long serialVersionUID = 1L;
 
     /**
@@ -78,10 +76,20 @@
 
         final FloodDurationCalculationResults results = (FloodDurationCalculationResults) res.getData();
         final List<FloodDurationCalculationResult> resultList = results.getResults();
+
         int resultIndex = 0;
         int themeCount = 0;
         for (final FloodDurationCalculationResult result : resultList) {
 
+            if (resultIndex == 0) {
+                /* we only have one result, but safety first... */
+
+                /* Setting the valid stations as data to the state, so the NaviChartOutputTab knows what are the valid stations */
+                final List<Double> validDurationChartKilometers = result.getValidDurationChartKilometers();
+                final String validKilometerString = StringUtils.join(validDurationChartKilometers, ',');
+                sinfo.addStringData("validStations", validKilometerString);
+            }
+
             final FloodDurationAccess access = new FloodDurationAccess(sinfo);
             if ((access.getRiverside() == RiversideChoiceKey.LEFT) || (access.getRiverside() == RiversideChoiceKey.BOTH))
                 facets.add(FloodDurationProcessor.createFloodDurationFacet(context, hash, this.id, result, 0, resultIndex));
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodHeightProcessor.java	Tue Jul 17 19:48:23 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodHeightProcessor.java	Tue Jul 17 19:48:28 2018 +0200
@@ -109,7 +109,7 @@
                         return waterlevel.getWaterlevel();
                     }
                 };
-                final double[][] points = ((FloodDurationCalculationResult) data).getMainValueDurationPoints(generator, valuegetter, index);
+                final double[][] points = ((FloodDurationCalculationResult) data).getMainValueDurationPoints(valuegetter, index);
                 return buildSeriesForType(points, generator, bundle, theme, visible, null);
             }
         }

http://dive4elements.wald.intevation.org