diff artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java @ 8964:45f1ad66560e

Code cleanup concerning calculations: improved error handling; improved interpolation; bed heights are now always used for spatial discretisation
author gernotbelger
date Thu, 29 Mar 2018 15:48:17 +0200
parents 183f42641ab6
children b5600453bb8f
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java	Wed Mar 28 17:04:20 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java	Thu Mar 29 15:48:17 2018 +0200
@@ -16,6 +16,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.TreeSet;
 
 import org.apache.commons.lang.math.DoubleRange;
 import org.apache.commons.lang.math.NumberRange;
@@ -65,7 +66,7 @@
 
         /* find relevant bed-heights */
         final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(problems);
-        final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(calcRange, defaultBedHeights);
+        final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(problems, calcRange, defaultBedHeights);
 
         /* misuse winfo-artifact to calculate waterlevels in the same way */
         final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
@@ -85,17 +86,33 @@
         /* for each waterlevel, do a tkh calculation */
         final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange, descriptionHeader);
 
-        for (final WQKms wqKms : kms) {
+        /* determine calculation steps */
+        final Collection<Double> allStations = determineCalculationSteps(bedHeights);
 
-            final TkhCalculationResult result = calculateResult(calcRange, infoProvider, wqKms, bedHeights, descBuilder, problems);
+        for (final WQKms wqKms : kms) {
+            final TkhCalculationResult result = calculateResult(calcRange, allStations, infoProvider, wqKms, bedHeights, descBuilder, problems);
             if (result != null)
-                // FIXME: must be sorted by station!
                 results.addResult(result);
         }
 
         return new CalculationResult(results, problems);
     }
 
+    /**
+     * Calculation steps are simply the union of all stations of all involved bed-height datasets
+     */
+    private Collection<Double> determineCalculationSteps(final Collection<BedHeightsFinder> bedHeights) {
+
+        final Collection<Double> allStations = new TreeSet<>();
+
+        for (final BedHeightsFinder bedHeight : bedHeights) {
+            final Collection<Double> stations = bedHeight.getStations();
+            allStations.addAll(stations);
+        }
+
+        return allStations;
+    }
+
     private WQKms[] calculateWaterlevels(final WINFOArtifact winfo, final Calculation problems) {
 
         final CalculationResult waterlevelData = winfo.getWaterlevelData(this.context);
@@ -112,12 +129,12 @@
         return (WQKms[]) waterlevelData.getData();
     }
 
-    private TkhCalculationResult calculateResult(final DoubleRange calcRange, final RiverInfoProvider riverInfo, final WQKms wkms,
-            final Collection<BedHeightsFinder> bedHeights, final WaterlevelDescriptionBuilder descBuilder, final Calculation problems) {
+    private TkhCalculationResult calculateResult(final DoubleRange calcRange, final Collection<Double> allStations, final RiverInfoProvider riverInfo,
+            final WQKms wkms, final Collection<BedHeightsFinder> bedHeights, final WaterlevelDescriptionBuilder descBuilder, final Calculation problems) {
 
-        // FIXME: wo kommt das her? via winfo kein jahr vorhanden, oder doch? aber soll in metadaten ausgegeben werden...
+        // We have no wst year as the wst is created by a calculation; we do not need it though
         final int wspYear = -1;
-        // FIXME: richtig? vgl. WInfo?
+        // 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);
 
@@ -137,14 +154,9 @@
 
         final Collection<SInfoResultRow> rows = new ArrayList<>();
 
-        /* using wst-kms as basis, because we know that they are generated wst's with a fixed km-step */
-        // FIXME: das führt dazu, das aktuell die Sohlhöhen beliebig linear interpolierrt werden. ist das immer richtig? z.b.
-        // bei großen abständen?
+        for (final Double stationDbl : allStations) {
 
-        final int size = wkms.size();
-        for (int i = 0; i < size; i++) {
-
-            final double station = wkms.getKm(i);
+            final double station = stationDbl;
 
             /* find the right calculator (i.e. bed height) depending on station, there should only be one maximal */
             final TkhCalculator tkhCalculator = findCalculator(calculatorsByRanges, station);
@@ -188,15 +200,15 @@
 
             final NumberRange range = new NumberRange(info.getFrom(), info.getTo());
 
-            final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(wkms);
+            final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wkms);
             final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms);
 
             /* initialize tkh calculator */
-            final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, this.context, problems, wstLabel, riverInfoProvider.getRiver(),
-                    calcRange, waterlevelProvider, dischargeProvider, bedHeightsProvider);
+            final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, problems, wstLabel, riverInfoProvider.getRiver(), calcRange,
+                    waterlevelProvider, dischargeProvider, bedHeightsProvider);
 
-            if (tkhCalculator != null) {
-                /* just ignore null ones, problems have already been updated by buildTkhCalculator() */
+            if (tkhCalculator.hasTkh()) {
+                /* just ignore invalid ones, problems have already been updated by buildTkhCalculator() */
                 calculatorByRanges.put(range, tkhCalculator);
             }
         }

http://dive4elements.wald.intevation.org