# HG changeset patch
# User mschaefer
# Date 1533915106 -7200
# Node ID 439699ff9b2d977d479db7f71bd35e5b08cfdfaf
# Parent 6174daaf5e5695731168a8fd982a48eb8151124e
Added U-Info iota (prev. salix) calculation for historical scenario
diff -r 6174daaf5e56 -r 439699ff9b2d artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedHeightsFinder.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedHeightsFinder.java Fri Aug 10 17:07:30 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/BedHeightsFinder.java Fri Aug 10 17:31:46 2018 +0200
@@ -102,7 +102,7 @@
*
* @return null
if no bed height with the given id exists.
*/
- private static BedHeightsFinder forId(final Calculation problems, final int id, final DoubleRange range) {
+ public static BedHeightsFinder forId(final Calculation problems, final int id, final DoubleRange range) {
final BedHeight bedHeight = BedHeight.getBedHeightById(id);
if (bedHeight == null)
@@ -153,6 +153,12 @@
return this.values.keySet();
}
+ public DoubleRange getKmRange() {
+ if (this.values.isEmpty())
+ return null;
+ return new DoubleRange(this.values.firstKey().doubleValue(), this.values.lastKey().doubleValue());
+ }
+
public double getMeanBedHeight(final double km) {
return interpolateBedHeights(km, BedHeightValueType.value);
}
diff -r 6174daaf5e56 -r 439699ff9b2d artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/DefaultBedHeights.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/DefaultBedHeights.java Fri Aug 10 17:07:30 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/DefaultBedHeights.java Fri Aug 10 17:31:46 2018 +0200
@@ -22,11 +22,11 @@
import org.dive4elements.river.model.River;
/**
- * This class knows how to find the default bed heights defined for tkh calculation
+ * This class knows how to find the default bed heights defined for tkh and other calculations
*
* @author Gernot Belger
*/
-final class DefaultBedHeights {
+public final class DefaultBedHeights {
private final River river;
diff -r 6174daaf5e56 -r 439699ff9b2d artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineAccess.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineAccess.java Fri Aug 10 17:07:30 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineAccess.java Fri Aug 10 17:31:46 2018 +0200
@@ -99,6 +99,18 @@
return super.getString("supraregional_table");
}
+ /**
+ * Database id of the selected sounding, or 0
+ */
+ public int getBedHeightId() {
+ final BedHeightAccess access = new BedHeightAccess(this.artifact);
+ final int[] ids = access.getBedHeightIDs();
+ if ((ids != null) && (ids.length > 0)) {
+ return ids[0];
+ }
+ return 0;
+ }
+
public BedHeight getBedHeight() { // TODO: make lazy? Aber achtung, falls der user zurückgeht und ne andere Peilung auswählt...
final BedHeightAccess access = new BedHeightAccess(this.artifact);
final int[] ids = access.getBedHeightIDs();
diff -r 6174daaf5e56 -r 439699ff9b2d artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java Fri Aug 10 17:07:30 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java Fri Aug 10 17:31:46 2018 +0200
@@ -10,6 +10,7 @@
package org.dive4elements.river.artifacts.uinfo.salix;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.NavigableMap;
import java.util.TreeMap;
@@ -22,26 +23,39 @@
import org.dive4elements.river.artifacts.model.CalculationResult;
import org.dive4elements.river.artifacts.resources.Resources;
import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsUtils;
+import org.dive4elements.river.artifacts.sinfo.tkhstate.DefaultBedHeights;
import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils;
import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType;
+import org.dive4elements.river.model.BedHeight;
import org.dive4elements.river.model.River;
+import org.dive4elements.river.utils.Formatter;
/**
+ * Calculation of a iota (former salix) longitudinal section, optionally with a delta scenario
+ *
* @author Domenico Nardi Tironi
+ * @author Matthias Schäfer
*
*/
final class SalixLineCalculation {
private final CallContext context;
+ private Calculation problems;
+
public SalixLineCalculation(final CallContext context) {
this.context = context;
}
+ /**
+ * Calculates the iota longitudinal section and delta scenario of a uinfo artifact
+ */
public CalculationResult calculate(final UINFOArtifact uinfo) {
- final Calculation problems = new Calculation();
+ this.problems = new Calculation();
final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name());
final String user = CalculationUtils.findArtifactUser(this.context, uinfo);
@@ -62,14 +76,14 @@
final SalixLineCalculator calculator = new SalixLineCalculator(riverInfoProvider);
final NavigableMap> rangeScenarios = buildRangeScenarios(accessSalix);
- calculator.execute(problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix),
+ calculator.execute(this.problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix),
buildAdditionalString(accessSalix), results);
- return new CalculationResult(results, problems);
+ return new CalculationResult(results, this.problems);
}
/**
- * Build a map of delta-Ws by from-km for the selected scenario
+ * Builds a map of delta-Ws by from-km for the selected scenario
*/
private NavigableMap> buildRangeScenarios(final SalixLineAccess access) {
final NavigableMap> rangeScenarios = new TreeMap<>();
@@ -78,8 +92,8 @@
access.getRegionalScenarioIntegers());
else if (access.getScenario() == ScenarioType.SUPRAREGIONAL)
fillRangeScenarios(rangeScenarios, access.getSupraRegionalString());
- // TODO else if (access.getScenario().equals(ScenarioType.HISTORICAL.getKey()))
- // historisches Szenario aus MSH etc.
+ else if (access.getScenario() == ScenarioType.HISTORICAL)
+ fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(), access.getBedHeightId());
else
fillRangeScenarios(rangeScenarios, access);
@@ -87,23 +101,23 @@
}
/**
- * Fill a map of delta-Ws with only one 0-delta for the whole calc range (no scenario)
+ * Fills a map of delta-Ws with only one 0-delta for the whole calc range (no scenario)
*/
private void fillRangeScenarios(final NavigableMap> rangeScenarios, final RangeAccess calcRange) {
final List nulls = new ArrayList<>();
- nulls.add(0.0);
+ nulls.add(null);
rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls);
}
/**
- * Fill a map of delta-Ws by km-range from the regional scenario input data
+ * Fills a map of delta-Ws by km-range from the regional scenario input data
*/
- private void fillRangeScenarios(final NavigableMap> rangeScenarios, final RangeAccess calcRange, final double partFrom,
- final double partTo, final int[] deltaWs) {
+ private void fillRangeScenarios(final NavigableMap> rangeScenarios, final RangeAccess calcRange,
+ final double partFrom, final double partTo, final int[] deltaWs) {
final List nulls = new ArrayList<>();
final List dwsm = new ArrayList<>();
for (int i = 0; i <= deltaWs.length - 1; i++) {
- nulls.add(0.0);
+ nulls.add(null);
dwsm.add(deltaWs[i] / 100.0);
}
rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls);
@@ -112,20 +126,65 @@
}
/**
- * Fill a map of delta-Ws by km-range from the supraregional scenario input data
+ * Fills a map of delta-Ws by km-range from the supraregional scenario input data
* (the zones input by the user cover the calc range completely)
*/
private void fillRangeScenarios(final NavigableMap> rangeScenarios, final String zones) {
final List parts = SalixZone.parse(zones);
for (final SalixZone part : parts) {
final List dwsm = new ArrayList<>();
- dwsm.add(part.getDwsplValue() / 100.0);
+ if (part.getDwsplValue() == 0)
+ dwsm.add(null);
+ else
+ dwsm.add(part.getDwsplValue() / 100.0);
rangeScenarios.put(Double.valueOf(part.getFromKm().doubleValue() - 0.0001), dwsm);
}
}
/**
- * Build the list of delta-w labels for the scenario type
+ * Fetches historical and reference bed heights and fills a map of delta-MSHs for all fetched stations in the calc range
+ */
+ private void fillRangeScenarios(final NavigableMap> rangeScenarios, final RangeAccess calcRange,
+ final double partFrom, final double partTo, final int historicalBedHeightId) {
+
+ // Find relevant default bed-heights
+ final River river = calcRange.getRiver();
+ final List defaultBedHeights = new DefaultBedHeights(river).getBedHeights(this.problems);
+ if (defaultBedHeights.isEmpty())
+ return;
+ final DoubleRange scenarioRange = new DoubleRange(partFrom, partTo);
+ final Collection allFinders = BedHeightsFinder.createTkhBedHeights(this.problems, scenarioRange, defaultBedHeights);
+ final Collection currentFinders = new ArrayList<>(allFinders);
+
+ // Add historical bed-heights
+ final BedHeightsFinder historicalFinder = BedHeightsFinder.forId(this.problems, historicalBedHeightId, scenarioRange);
+ allFinders.add(historicalFinder);
+ final Collection stations = BedHeightsUtils.extractStationCollection(allFinders, true);
+ final List nulls = new ArrayList<>();
+ nulls.add(null);
+ rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls);
+ for (final Double station : stations) {
+ rangeScenarios.put(station, new ArrayList());
+ rangeScenarios.get(station).add(Double.valueOf(bedHeightDifference(station.doubleValue(), currentFinders, historicalFinder)));
+ }
+ rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls);
+ }
+
+ /**
+ * Gets the difference of a historical bed height against a current one for a station
+ */
+ private double bedHeightDifference(final double station, final Collection currentFinders, final BedHeightsFinder historicalFinder) {
+ double currentMSH = Double.NaN;
+ for (final BedHeightsFinder bhf : currentFinders) {
+ currentMSH = bhf.getMeanBedHeight(station);
+ if (!Double.isNaN(currentMSH))
+ break;
+ }
+ return Formatter.roundFlowDepth(historicalFinder.getMeanBedHeight(station)).subtract(Formatter.roundFlowDepth(currentMSH)).doubleValue();
+ }
+
+ /**
+ * Builds the list of delta-w labels for the scenario type
*/
private String[] buildScenarioLabels(final SalixLineAccess access) {
final List labels = new ArrayList<>();
@@ -142,7 +201,7 @@
}
/**
- * Build the km range string for the scenario type
+ * Builds the km range string for the scenario type
*/
private String buildPartialRangeString(final SalixLineAccess access) {
if ((access.getScenario() == ScenarioType.REGIONAL) || (access.getScenario() == ScenarioType.HISTORICAL)) {
@@ -166,7 +225,7 @@
}
/**
- * Build the delta w or time string for the scenario type
+ * Builds the delta w or time string for the scenario type
*/
private String buildAdditionalString(final SalixLineAccess access) {
if (access.getScenario() == ScenarioType.REGIONAL) {
diff -r 6174daaf5e56 -r 439699ff9b2d artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java Fri Aug 10 17:07:30 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java Fri Aug 10 17:31:46 2018 +0200
@@ -139,7 +139,7 @@
final ResultRow row = ResultRow.create();
row.putValue(GeneralResultType.station, station);
- // Find station's gauge
+ // Find station's gauge (obsolete version which calculates gauge-wise)
// final Gauge gauge = this.riverInfoProvider.getGauge(station, true);
// Interpolate mnw, mw, and mhw
// final double mnw = interpolateW(station, this.gaugeMnwPos.get(gauge));
@@ -156,11 +156,11 @@
row.putValue(UInfoResultType.salix_mw_mnw, calcMwmnw(mw, mnw));
// Calc scenario values (always all scenario types set, Result variant extracts the fields needed)
final List scenarios = new ArrayList<>();
- final double[] deltaws = getDeltaWs(station, rangeScenarios);
- for (int i = 0; i <= deltaws.length - 1; i++) {
- if (Math.abs(deltaws[i]) > 0.0001) {
- final double salix = calcSalix(mhw, mw + deltaws[i]);
- scenarios.add(new SalixScenario((int) (deltaws[i] * 100), salix));
+ final List deltaws = getDeltaWs(station, rangeScenarios);
+ for (final Double deltaw : deltaws) {
+ if (deltaw != null) {
+ final double salix = calcSalix(mhw, mw + deltaw);
+ scenarios.add(new SalixScenario((int) (deltaw * 100), salix));
}
else {
scenarios.add(null);
@@ -198,16 +198,15 @@
}
/**
- * Gets the station-specific list of delta-ws of the active scenario, at least with one 0 item in any case
+ * Gets the station-specific list of delta-ws of the active scenario, at least with one null item in any case
*/
- private double[] getDeltaWs(final double station, final NavigableMap> rangeScenarios) {
+ private List getDeltaWs(final double station, final NavigableMap> rangeScenarios) {
final Entry> stationScenarios = rangeScenarios.floorEntry(station);
- if (stationScenarios == null)
- return new double[] { 0.0 };
-
- final double[] deltaws = new double[stationScenarios.getValue().size()];
- for (int i = 0; i <= stationScenarios.getValue().size() - 1; i++)
- deltaws[i] = stationScenarios.getValue().get(i);
- return deltaws;
+ if (stationScenarios != null) {
+ return stationScenarios.getValue();
+ }
+ final List noScen = new ArrayList<>();
+ noScen.add(null);
+ return noScen;
}
}
\ No newline at end of file