[PATCH] Cleanup of MainWstValue code. Cache qPositions once determined
Wald Commits
scm-commit at wald.intevation.org
Tue Oct 2 13:25:47 CEST 2018
# HG changeset patch
# User gernotbelger
# Date 1538479552 -7200
# Node ID 7c8d6286787627cc14e138d3bdcb64b7c8415752
# Parent 51212d40ff56788e61a4b36847da20adc079fb46
Cleanup of MainWstValue code. Cache qPositions once determined.
diff -r 51212d40ff56 -r 7c8d62867876 artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/MainWstValues.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/MainWstValues.java Tue Oct 02 13:25:52 2018 +0200
@@ -0,0 +1,102 @@
+/** 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
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.artifacts.model.river;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.model.Gauge;
+import org.dive4elements.river.model.MainValue;
+import org.dive4elements.river.model.MainValueType;
+import org.dive4elements.river.model.NamedMainValue;
+import org.dive4elements.river.model.River;
+
+/**
+ * @author Gernot Belger
+ */
+public final class MainWstValues {
+
+ private static final Map<String, MainWstValues> values = new HashMap<>();
+
+ public synchronized static MainWstValues forRiver(final River river) {
+
+ final String riverName = river.getName();
+ if (values.containsKey(riverName))
+ return values.get(riverName);
+
+ /* determine q main values of first upstream gauge */
+ final Gauge gauge = river.firstUpstreamGauge();
+
+ /* determine reference station */
+ // REAMRK: we will be using the station of the gauge (not the start of the range) to determine the q-Position,
+ // because we are using the discharge of the main value of the gauge. Hopefully .wt file and main values are always
+ // synchrone...
+ final BigDecimal referenceStation = gauge.getStation();
+
+ /* determine q-positions for all main values */
+ // REMARK: wst is cached, so we get it when we need it and do not remember it
+ final WstValueTable wst = WstValueTableFactory.getTable(river);
+
+ final Map<String, QPosition> mainValuePositions = new HashMap<>();
+
+ final List<MainValue> mainValues = gauge.getMainValues();
+ for (final MainValue mainValue : mainValues) {
+ final NamedMainValue nmv = mainValue.getMainValue();
+ if (nmv.getType().getName().equals(MainValueType.MainValueTypeKey.Q.getName())) {
+ final BigDecimal discharge = mainValue.getValue();
+ final String name = nmv.getName();
+
+ final QPosition qPosition = wst.getQPosition(referenceStation.doubleValue(), discharge.doubleValue());
+ mainValuePositions.put(name.toUpperCase(), qPosition);
+ }
+ }
+
+ final MainWstValues mainWstValues = new MainWstValues(river.getName(), mainValuePositions);
+ values.put(riverName, mainWstValues);
+ return mainWstValues;
+ }
+
+ private final Map<String, QPosition> mainValuePositions;
+
+ private final String riverName;
+
+ private MainWstValues(final String riverName, final Map<String, QPosition> mainValuePositions) {
+ this.riverName = riverName;
+ this.mainValuePositions = mainValuePositions;
+ }
+
+ public boolean hasPosition(final String mainValueName) {
+
+ final QPosition qPosition = this.mainValuePositions.get(mainValueName.toUpperCase());
+ return qPosition != null;
+ }
+
+ public double getW(final River river, final String mainValueName, final double station) {
+ // REMARK: we do not keep the river, as it is a hibernate object and this instance is statically cached.
+ // However, we need to make sure we are not misused with another river
+ // We also do not look up the river by its name here, because thats a database access
+ if (!river.getName().equals(this.riverName))
+ throw new IllegalStateException();
+
+ // REMARK: wst is cached, so we get it when we need it and do not remember it
+ final WstValueTable wst = WstValueTableFactory.getTable(river);
+
+ final QPosition qPosition = this.mainValuePositions.get(mainValueName.toUpperCase());
+ if (qPosition == null)
+ return Double.NaN;
+
+ return wst.interpolateW(station, qPosition);
+ }
+}
\ No newline at end of file
diff -r 51212d40ff56 -r 7c8d62867876 artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/MainWstValuesCalculator.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/river/MainWstValuesCalculator.java Mon Oct 01 18:08:31 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/** 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
- * documentation coming with Dive4Elements River for details.
- */
-package org.dive4elements.river.artifacts.model.river;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.lang.math.DoubleRange;
-import org.dive4elements.artifacts.CallContext;
-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.model.Gauge;
-import org.dive4elements.river.model.MainValue;
-import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
-import org.dive4elements.river.model.River;
-
-/**
- * @author Domenico Nardi Tironi
- */
-public final class MainWstValuesCalculator {
-
- private final WstValueTable wst;
-
- private final Map<String, MainValueQPosition> positions;
-
- static class MainValueQPosition {
-
- public final Map<Gauge, QPosition> gaugePositions = new HashMap<>();
-
- public QPosition refGaugePositions = null;
- }
-
- public static MainWstValuesCalculator forRiver(final CallContext context, final River river, final DoubleRange calcRange, final String... mainValueNames) {
-
- final RiverInfoProvider info = RiverInfoProvider.forRange(context, river, calcRange);
-
- return forRiverInfo(info, mainValueNames);
- }
-
- public static MainWstValuesCalculator forRiverInfo(final RiverInfoProvider info, final String... mainValueNames) {
-
- final WstValueTable wst = WstValueTableFactory.getTable(info.getRiver());
-
- final Map<String, MainValueQPosition> positions = calculatePositions(info, wst, mainValueNames);
-
- return new MainWstValuesCalculator(wst, positions);
- }
-
- private static Map<String, MainValueQPosition> calculatePositions(final RiverInfoProvider info, final WstValueTable wst, final String[] mainValueNames) {
-
- boolean isFirstGauge = true;
-
- final Map<String, MainValueQPosition> positions = new HashMap<>();
-
- for (final String mainValue : mainValueNames)
- positions.put(mainValue.toUpperCase(), new MainValueQPosition());
-
- for (final Gauge gauge : info.getGauges()) {
-
- for (final MainValueQPosition position : positions.values())
- position.gaugePositions.put(gauge, null);
-
- final double gaugeKm = gauge.getStation().doubleValue();
- for (final MainValue mv : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.Q)) {
-
- final MainValueQPosition position = positions.get(mv.getMainValue().getName().toUpperCase());
- if (position != null) {
- final QPosition qPosition = wst.getQPosition(gaugeKm, mv.getValue().doubleValue());
- position.gaugePositions.put(gauge, qPosition);
-
- if (isFirstGauge)
- position.refGaugePositions = qPosition;
- }
- }
-
- isFirstGauge = false;
- }
-
- return positions;
- }
-
- private MainWstValuesCalculator(final WstValueTable wst, final Map<String, MainValueQPosition> positions) {
- this.wst = wst;
- this.positions = positions;
- }
-
- public boolean hasPosition(final String mainValueName) {
-
- final MainValueQPosition position = this.positions.get(mainValueName.toUpperCase());
- if (position == null)
- throw new IllegalArgumentException();
-
- return position.refGaugePositions != null;
- }
-
- /**
- * Interpolates the W for a station with a fixed (virtual) wst column position
- */
- public double interpolateW(final double station, final String mainValueName) {
-
- final MainValueQPosition mainValuePosition = this.positions.get(mainValueName.toUpperCase());
-
- if (mainValuePosition.refGaugePositions == null)
- return Double.NaN;
-
- return this.wst.interpolateW(station, mainValuePosition.refGaugePositions);
- }
-}
\ No newline at end of file
diff -r 51212d40ff56 -r 7c8d62867876 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 Mon Oct 01 18:08:31 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java Tue Oct 02 13:25:52 2018 +0200
@@ -19,12 +19,13 @@
import org.dive4elements.river.artifacts.common.GeneralResultType;
import org.dive4elements.river.artifacts.common.ResultRow;
import org.dive4elements.river.artifacts.model.Calculation;
-import org.dive4elements.river.artifacts.model.river.MainWstValuesCalculator;
+import org.dive4elements.river.artifacts.model.river.MainWstValues;
import org.dive4elements.river.artifacts.model.river.RiverInfoProvider;
import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper;
import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
import org.dive4elements.river.artifacts.uinfo.common.UInfoResultType;
import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType;
+import org.dive4elements.river.model.River;
/**
* Calculation of the result rows of the u-info salix line calc mode
@@ -56,7 +57,7 @@
final ScenarioType scenarioType, final String[] scenarioLabels, final String rangeString, final String additionalString,
final SalixLineCalculationResults results) {
- final MainWstValuesCalculator mainWstValues = fetchGaugeMainValuePositions2(problems);
+ final MainWstValues mainWstValues = fetchWstMainValues(problems);
final WINFOArtifact winfo = new WinfoArtifactWrapper(uinfo);
winfo.addStringData("ld_mode", "distance");
@@ -87,39 +88,36 @@
}
}
- private MainWstValuesCalculator fetchGaugeMainValuePositions2(final Calculation problems) {
- final MainWstValuesCalculator mainWstValues = MainWstValuesCalculator.forRiverInfo(this.riverInfoProvider, MAIN_VALUE_MQ, MAIN_VALUE_MNQ,
- MAIN_VALUE_MHQ, MAIN_VALUE_HQ5);
+ private MainWstValues fetchWstMainValues(final Calculation problems) {
- if (!mainWstValues.hasPosition(MAIN_VALUE_MQ))
+ final MainWstValues values = MainWstValues.forRiver(this.riverInfoProvider.getRiver());
+
+ if (!values.hasPosition(MAIN_VALUE_MQ))
problems.addProblem("uinfo_salix_calc.warning.missing_mq");
else {
- if (!mainWstValues.hasPosition(MAIN_VALUE_MHQ))
+ if (!values.hasPosition(MAIN_VALUE_MHQ))
problems.addProblem("uinfo_salix_calc.warning.missing_mhq");
- if (!mainWstValues.hasPosition(MAIN_VALUE_MNQ))
+ if (!values.hasPosition(MAIN_VALUE_MNQ))
problems.addProblem("uinfo_salix_calc.warning.missing_mnq");
}
- return mainWstValues;
+ return values;
}
/**
* Create a result row for a station and its gauge, and add w-q-values as selected
*/
- private ResultRow createRow(final MainWstValuesCalculator mainWstValues, final double station, final NavigableMap<Double, List<Double>> rangeScenarios) {
+ private ResultRow createRow(final MainWstValues mainWstValues, final double station, final NavigableMap<Double, List<Double>> rangeScenarios) {
+
+ final River river = this.riverInfoProvider.getRiver();
final ResultRow row = ResultRow.create();
row.putValue(GeneralResultType.station, station);
- // 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));
- // final double mw = interpolateW(station, this.gaugeMwPos.get(gauge));
- // final double mhw = interpolateW(station, this.gaugeMhwPos.get(gauge));
- final double mnw = mainWstValues.interpolateW(station, MAIN_VALUE_MNQ);
- final double mw = mainWstValues.interpolateW(station, MAIN_VALUE_MQ);
- final double mhw = mainWstValues.interpolateW(station, MAIN_VALUE_MHQ);
- final double hw5 = mainWstValues.interpolateW(station, MAIN_VALUE_HQ5);
+
+ final double mnw = mainWstValues.getW(river, MAIN_VALUE_MNQ, station);
+ final double mw = mainWstValues.getW(river, MAIN_VALUE_MQ, station);
+ final double mhw = mainWstValues.getW(river, MAIN_VALUE_MHQ, station);
+ final double hw5 = mainWstValues.getW(river, MAIN_VALUE_HQ5, station);
row.putValue(UInfoResultType.waterlevelMNW, mnw);
row.putValue(UInfoResultType.waterlevelMW, mw);
row.putValue(UInfoResultType.waterlevelMHW, mhw);
diff -r 51212d40ff56 -r 7c8d62867876 artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCrossSectionProcessor.java
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCrossSectionProcessor.java Mon Oct 01 18:08:31 2018 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/vegetationzones/VegetationZonesCrossSectionProcessor.java Tue Oct 02 13:25:52 2018 +0200
@@ -23,7 +23,7 @@
import org.dive4elements.river.artifacts.D4EArtifact;
import org.dive4elements.river.artifacts.access.RiverAccess;
import org.dive4elements.river.artifacts.model.CrossSectionFacetUtils;
-import org.dive4elements.river.artifacts.model.river.MainWstValuesCalculator;
+import org.dive4elements.river.artifacts.model.river.MainWstValues;
import org.dive4elements.river.artifacts.resources.Resources;
import org.dive4elements.river.exports.CrossSectionGenerator;
import org.dive4elements.river.jfree.StripedAreaDataset;
@@ -87,8 +87,8 @@
for (final VegetationZoneServerClientXChange zone : zones) {
- final double lower = uefdToHeight(context, river, currentStation, zone.getLowerFromTo());
- final double upper = uefdToHeight(context, river, currentStation, zone.getUpperFromTo());
+ final double lower = uefdToHeight(river, currentStation, zone.getLowerFromTo());
+ final double upper = uefdToHeight(river, currentStation, zone.getUpperFromTo());
final Color color = Color.decode(zone.getHexColor());
final String label = String.format("%s (%dd-%dd)", zone.getZoneName(), zone.getLowerFromTo(), zone.getUpperFromTo());
@@ -116,12 +116,10 @@
throw new UnsupportedOperationException();
}
- private static double uefdToHeight(final CallContext context, final River river, final double station, final int uefd) {
+ private static double uefdToHeight(final River river, final double station, final int uefd) {
- // FIXME: cache me
- final MainWstValuesCalculator mainWstValues = MainWstValuesCalculator.forRiver(context, river, null, MAIN_VALUE_MQ);
-
- final double mw = mainWstValues.interpolateW(station, MAIN_VALUE_MQ);
+ final MainWstValues mainWstValues = MainWstValues.forRiver(river);
+ final double mw = mainWstValues.getW(river, MAIN_VALUE_MQ, station);
// Üfd = -70,559 ∗ ln((DGM - MW) + 0,5) + 80,711
final double f1 = -70.559;
diff -r 51212d40ff56 -r 7c8d62867876 backend/src/main/java/org/dive4elements/river/model/River.java
--- a/backend/src/main/java/org/dive4elements/river/model/River.java Mon Oct 01 18:08:31 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/model/River.java Tue Oct 02 13:25:52 2018 +0200
@@ -14,6 +14,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.NavigableMap;
import java.util.TreeMap;
import javax.persistence.Column;
@@ -427,5 +428,27 @@
}
return null;
}
+
+ public Gauge firstUpstreamGauge() {
+ final List<Gauge> gauges = getGauges();
+
+ final NavigableMap<BigDecimal, Gauge> byKm = new TreeMap<>();
+
+ for (final Gauge gauge : gauges) {
+ final Range range = gauge.getRange();
+ if (range != null) {
+ final BigDecimal a = range.getA();
+ byKm.put(a, gauge);
+ }
+ }
+
+ if (byKm.isEmpty())
+ return null;
+
+ if (kmUp)
+ return byKm.lastEntry().getValue();
+
+ return byKm.firstEntry().getValue();
+ }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
More information about the Dive4Elements-commits
mailing list