changeset 9528:55c187a0a31e

Fixed: consistent gauge assignment with downstream gauge as reference gauge for calc range starting at a gauge range limit
author mschaefer
date Tue, 02 Oct 2018 16:39:51 +0200
parents 7c8d62867876
children 429b62373633
files artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/RiverInfoProvider.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/FloodDurationCalculator.java artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java
diffstat 5 files changed, 50 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java	Tue Oct 02 13:25:52 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/bundu/bezugswst/BezugswstCalculation.java	Tue Oct 02 16:39:51 2018 +0200
@@ -35,6 +35,7 @@
 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
 import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
+import org.dive4elements.river.artifacts.states.WaterlevelData;
 import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
 import org.dive4elements.river.model.BedHeightValueType;
 import org.dive4elements.river.model.River;
@@ -93,13 +94,19 @@
         // Calculate the wspl for the selected river range as in fixa awspl
         bunduartifact.addStringData("wq_isq", "true");
         final WinfoArtifactWrapper winfo = new WinfoArtifactWrapper(bunduartifact);
-        final RiverInfoProvider riverInfoProvider = RiverInfoProvider.forRange(this.context, river, access.getRange(), true);
+        final RiverInfoProvider riverInfoProvider = RiverInfoProvider.forRange(this.context, river, access.getRange());
         final FixRealizingResult fixResult = calculateWspl(bunduartifact, problems);
         if (fixResult == null)
             return new CalculationResult(results, problems);
 
         final WQKms wqkms = fixResult.getWQKms()[0];
-        final WstInfo wstInfo = new WstInfo(wqkms.getName(), 0, riverInfoProvider.getReferenceGauge(), true);
+        // We have no wst year as the wst is created by a calculation; we do not need it though
+        final int wspYear = -1;
+        // Remark: showAllGauges true for Fixierungsanalyse, false for WInfo, so true here as well
+        final boolean showAllGauges = true;
+        final WaterlevelData waterlevel = new WaterlevelData(wqkms, wspYear, showAllGauges, true);
+        final RiverInfoProvider riverInfoProvider2 = riverInfoProvider.forWaterlevel(waterlevel);
+        final WstInfo wstInfo = new WstInfo(wqkms.getName(), 0, riverInfoProvider2.getReferenceGauge(), true);
 
         // Fetch the bed heights of the selected sounding
         final Integer bedHeightId = access.getBedHeightID();
@@ -113,7 +120,7 @@
 
         // Compute the result rows
         for (int i = 0; i <= wqkms.size() - 1; i++) {
-            this.rows.add(createRow(wqkms.getKm(i), wqkms.getW(i), wqkms.getQ(i), bedHeightsFinder, channelFinder, riverInfoProvider, wstInfo));
+            this.rows.add(createRow(wqkms.getKm(i), wqkms.getW(i), wqkms.getQ(i), bedHeightsFinder, channelFinder, riverInfoProvider2, wstInfo));
         }
 
         // Compute the missing volumes
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/RiverInfoProvider.java	Tue Oct 02 13:25:52 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/RiverInfoProvider.java	Tue Oct 02 16:39:51 2018 +0200
@@ -37,31 +37,16 @@
 
     public static RiverInfoProvider forRange(final CallContext context, final River river, final DoubleRange calcRange) {
 
-        return forRange(context, river, calcRange, false);
-    }
-
-    public static RiverInfoProvider forRange(final CallContext context, final River river, final DoubleRange calcRange, final boolean firstGaugeIsRefGauge) {
-
         final List<Gauge> gauges;
         if (calcRange == null)
             gauges = river.getGauges();
-        else {
+        else
             gauges = river.determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble());
 
-            // If the range starts exactly at a gauge's range end, determineGauges gets this gauge as the first in list,
-            // but we want the list to start with the next gauge, i.e. that one that starts with the calc range,
-            // therefore we remove the first one
-            // REMARK Bei abwärts kilometriertem Fluss den letzten Gauge in der Liste prüfen (Ende)/entfernen
-            if ((gauges.size() >= 2) && (Math.abs(gauges.get(0).getRange().getB().doubleValue() - calcRange.getMinimumDouble()) < 0.0001))
-                gauges.remove(0);
-        }
-
         final GaugeIndex gaugeIndex = new GaugeIndex(gauges);
 
         final String notinrange = Resources.getMsg(context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE);
 
-        if (firstGaugeIsRefGauge && !gauges.isEmpty())
-            return new RiverInfoProvider(notinrange, river, false, gaugeIndex, gauges.get(0));
         return new RiverInfoProvider(notinrange, river, false, gaugeIndex, null);
     }
 
@@ -73,6 +58,9 @@
         this.refGauge = refGauge;
     }
 
+    /**
+     * Creates a new provider as a copy of this one, re-determining the reference gauge by a waterlevel
+     */
     public RiverInfoProvider forWaterlevel(final WaterlevelData waterlevel) {
         final WKms wstKms = waterlevel.getWkms();
         final Gauge waterlevelRefGauge = findReferenceGauge(wstKms);
@@ -82,7 +70,15 @@
     }
 
     /**
-     * Re-determines the reference gauge, in the same way as the WaterlevelArtifact would do it
+     * Create a new provider as a copy of this one, re-determining the reference gauge by the upstream side of a range
+     */
+    public RiverInfoProvider forReferenceRange(final DoubleRange range, final boolean isShowAllGauges) {
+        final Gauge kmRefGauge = findReferenceGauge(range);
+        return new RiverInfoProvider(this.notinrange, this.river, isShowAllGauges, this.gaugeIndex, kmRefGauge);
+    }
+
+    /**
+     * Determines the reference gauge, in the same way as the WaterlevelArtifact would do it
      */
     private Gauge findReferenceGauge(final WKms wkms) {
 
@@ -90,6 +86,18 @@
         return this.river.determineRefGauge(wstFromTo, true);
     }
 
+    /**
+     * Determines the reference gauge for a km range of the active river
+     */
+    private Gauge findReferenceGauge(final DoubleRange range) {
+
+        final double from = range.getMinimumDouble();
+        final double to = range.getMaximumDouble();
+        final boolean waterIncreasing = this.river.getKmUp();
+        final double[] wstFromTo = waterIncreasing ? new double[] { to, from } : new double[] { from, to };
+        return this.river.determineRefGauge(wstFromTo, true);
+    }
+
     private static double[] findWstFromTo(final WKms wkms) {
 
         final double from = wkms.getKm(0);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java	Tue Oct 02 13:25:52 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculation.java	Tue Oct 02 16:39:51 2018 +0200
@@ -50,7 +50,7 @@
         final RiverInfo riverInfo = new RiverInfo(river);
         final DoubleRange calcRange = access.getRange();
 
-        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange, true);
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
         final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
         final String label = Resources.getMsg(this.context.getMeta(), access.getRiverside().getKey());
 
@@ -88,7 +88,7 @@
         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, true);
+        final RiverInfoProvider infoProvider = RiverInfoProvider.forRange(this.context, river, calcRange);
 
         final Calculation problems = new Calculation();
 
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Tue Oct 02 13:25:52 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flood_duration/FloodDurationCalculator.java	Tue Oct 02 16:39:51 2018 +0200
@@ -55,12 +55,14 @@
     private final List<ResultRow> rows = new ArrayList<>();
 
     private final RiverInfoProvider riverInfoProvider;
+    private RiverInfoProvider riverInfoProvider2;
 
     private final CallContext context;
 
     public FloodDurationCalculator(final CallContext context, final RiverInfoProvider riverInfoProvider) {
         this.context = context;
         this.riverInfoProvider = riverInfoProvider;
+        this.riverInfoProvider2 = null;
     }
 
     /**
@@ -71,7 +73,7 @@
 
         // Find all gauges of the calc range, and create the duration finders
         final Map<Gauge, GaugeDurationValuesFinder> durFinders = new HashMap<>();
-        for (final Gauge gauge : this.riverInfoProvider.getRiver().determineGauges(calcRange.getMinimumDouble(), calcRange.getMaximumDouble())) {
+        for (final Gauge gauge : this.riverInfoProvider.getGauges()) {
             durFinders.put(gauge, GaugeDurationValuesFinder.loadValues(gauge, problems));
         }
 
@@ -90,6 +92,10 @@
 
         // Calculate W and Q for all stations and the selected discharge states/waterlevels
         final WQKms[] wqkmsArray = calculateWsts(winfo, withWspl, stationsSorted, problems);
+        // final WaterlevelData waterlevel = new WaterlevelData(wqkmsArray[0], -1, false, true);
+        // this.riverInfoProvider2 = this.riverInfoProvider.forWaterlevel(waterlevel);
+        this.riverInfoProvider2 = this.riverInfoProvider.forReferenceRange(calcRange, false);
+        // this.riverInfoProvider2.cleanupGaugesAtStart(calcRange);
 
         // Determine discharge state labels of the waterlevels
         updateWstLabels(wqkmsArray, winfo, problems);
@@ -100,11 +106,11 @@
 
         // Load base wst table (river).wst
         // (should be in cache since already used in calculateWaterlevels (winfo.computeWaterlevelData)
-        final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
+        final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider2.getRiver());
 
         // Create the result rows, and calculate and add the flood durations etc.
         for (int i = 0; i <= stationsSorted.length - 1; i++) {
-            final Gauge gauge = this.riverInfoProvider.getGauge(stationsSorted[i], true);
+            final Gauge gauge = this.riverInfoProvider2.getGauge(stationsSorted[i], true);
             final ResultRow row = createRow(stationsSorted[i], wqkmsArray, gaugeWstDurations.get(gauge), i);
             if (allStations.containsKey(stationsSorted[i]) && (allStations.get(stationsSorted[i]) != null))
                 calculateInfrastructure(row, gauge, allStations.get(stationsSorted[i]), wst, durFinders);
@@ -132,7 +138,7 @@
     public WQDay calcWQDays(final Calculation problems, final double station, final WINFOArtifact winfo) {
 
         final WstValueTable wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
-        final Gauge gauge = this.riverInfoProvider.getRiver().determineGaugeByPosition(station);
+        final Gauge gauge = this.riverInfoProvider.getGauge(station, true);
         final Object[] obj = gauge.fetchDurationCurveData();
         final int[] udays = (int[]) obj[0];
         final double[] qs = (double[]) obj[1];
@@ -421,10 +427,10 @@
         row.putValue(SInfoResultType.infrastructuretype, null); // is replaced later for an infrastructure
         row.putValue(SInfoResultType.floodDuration, Double.NaN); // is replaced later for an infrastructure
 
-        final String gaugeLabel = this.riverInfoProvider.findGauge(station);
+        final String gaugeLabel = this.riverInfoProvider2.findGauge(station);
         row.putValue(GeneralResultType.gaugeLabel, gaugeLabel);
 
-        final String location = this.riverInfoProvider.getLocation(station);
+        final String location = this.riverInfoProvider2.getLocation(station);
         row.putValue(GeneralResultType.location, location);
 
         final List<DurationWaterlevel> wsts = new ArrayList<>(wqkmsArray.length);
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java	Tue Oct 02 13:25:52 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java	Tue Oct 02 16:39:51 2018 +0200
@@ -40,7 +40,6 @@
 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
 import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
-import org.dive4elements.river.artifacts.states.WaterlevelData;
 import org.dive4elements.river.exports.WaterlevelDescriptionBuilder;
 import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.River;
@@ -158,9 +157,8 @@
         final int wspYear = -1;
         // Remark: showAllGauges only true for Fixierungsanalyse, false for WInfo, so false here as well
         final boolean showAllGauges = false;
-        final WaterlevelData waterlevel = new WaterlevelData(wkms, wspYear, showAllGauges, true);
 
-        final RiverInfoProvider riverInfoProvider = riverInfo.forWaterlevel(waterlevel);
+        final RiverInfoProvider riverInfoProvider = riverInfo.forReferenceRange(calcRange, showAllGauges);
 
         final String waterlevelLabel = descBuilder.getDesc(wkms);
 

http://dive4elements.wald.intevation.org