comparison artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculator.java @ 9499:853f2dafc16e

VegetationZones in CrossSectionsDiagram
author gernotbelger
date Thu, 27 Sep 2018 18:06:26 +0200
parents e44c1a8b0c54
children 76c0665888a3
comparison
equal deleted inserted replaced
9496:d8e753d0fdb9 9499:853f2dafc16e
10 package org.dive4elements.river.artifacts.uinfo.salix; 10 package org.dive4elements.river.artifacts.uinfo.salix;
11 11
12 import java.math.BigDecimal; 12 import java.math.BigDecimal;
13 import java.util.ArrayList; 13 import java.util.ArrayList;
14 import java.util.Collection; 14 import java.util.Collection;
15 import java.util.HashMap;
16 import java.util.List; 15 import java.util.List;
17 import java.util.Map;
18 import java.util.Map.Entry; 16 import java.util.Map.Entry;
19 import java.util.NavigableMap; 17 import java.util.NavigableMap;
20 18
21 import org.dive4elements.river.artifacts.WINFOArtifact; 19 import org.dive4elements.river.artifacts.WINFOArtifact;
22 import org.dive4elements.river.artifacts.access.ComputationRangeAccess; 20 import org.dive4elements.river.artifacts.access.ComputationRangeAccess;
23 import org.dive4elements.river.artifacts.common.AbstractResultType; 21 import org.dive4elements.river.artifacts.common.AbstractResultType;
24 import org.dive4elements.river.artifacts.common.GeneralResultType; 22 import org.dive4elements.river.artifacts.common.GeneralResultType;
25 import org.dive4elements.river.artifacts.common.ResultRow; 23 import org.dive4elements.river.artifacts.common.ResultRow;
26 import org.dive4elements.river.artifacts.model.Calculation; 24 import org.dive4elements.river.artifacts.model.Calculation;
27 import org.dive4elements.river.artifacts.model.WstValueTable; 25 import org.dive4elements.river.artifacts.model.river.MainWstValuesCalculator;
28 import org.dive4elements.river.artifacts.model.WstValueTable.QPosition; 26 import org.dive4elements.river.artifacts.model.river.RiverInfoProvider;
29 import org.dive4elements.river.artifacts.model.WstValueTableFactory;
30 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider;
31 import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper; 27 import org.dive4elements.river.artifacts.sinfo.tkhstate.WinfoArtifactWrapper;
32 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; 28 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact;
33 import org.dive4elements.river.artifacts.uinfo.common.UInfoResultType; 29 import org.dive4elements.river.artifacts.uinfo.common.UInfoResultType;
34 import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; 30 import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType;
35 import org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZoneServerClientXChange; 31 import org.dive4elements.river.artifacts.uinfo.vegetationzones.VegetationZoneServerClientXChange;
36 import org.dive4elements.river.model.Gauge;
37 import org.dive4elements.river.model.MainValue;
38 import org.dive4elements.river.model.MainValueType.MainValueTypeKey;
39 import org.dive4elements.river.utils.Formatter; 32 import org.dive4elements.river.utils.Formatter;
40 33
41 /** 34 /**
42 * Calculation of the result rows of the u-info salix line calc mode 35 * Calculation of the result rows of the u-info salix line calc mode
43 * 36 *
44 * @author Matthias Schäfer 37 * @author Matthias Schäfer
45 */ 38 */
46 final class SalixLineCalculator { 39 final class SalixLineCalculator {
47 40
41 private static final String MAIN_VALUE_MNQ = "mnq";
42
43 private static final String MAIN_VALUE_MQ = "mq";
44
45 private static final String MAIN_VALUE_MHQ = "mhq";
46
47 private static final String MAIN_VALUE_HQ5 = "hq5";
48
48 private static final BigDecimal SALIX_DISTANCE = new BigDecimal("2.31"); 49 private static final BigDecimal SALIX_DISTANCE = new BigDecimal("2.31");
49 private final List<ResultRow> rows = new ArrayList<>(); 50 private final List<ResultRow> rows = new ArrayList<>();
50 51
51 private final RiverInfoProvider riverInfoProvider; 52 private final RiverInfoProvider riverInfoProvider;
52 53
53 private final Map<Gauge, QPosition> gaugeMwPos;
54 private final Map<Gauge, QPosition> gaugeMnwPos;
55 private final Map<Gauge, QPosition> gaugeMhwPos;
56 private final Map<Gauge, QPosition> gaugeHw5Pos;
57 private QPosition refGaugeMwPos;
58 private QPosition refGaugeMnwPos;
59 private QPosition refGaugeMhwPos;
60 private QPosition refGaugeHw5Pos;
61 private Gauge firstGauge;
62
63 private Calculation problems;
64
65 private WstValueTable wst;
66
67 public SalixLineCalculator(final RiverInfoProvider riverInfoProvider) { 54 public SalixLineCalculator(final RiverInfoProvider riverInfoProvider) {
68 this.riverInfoProvider = riverInfoProvider; 55 this.riverInfoProvider = riverInfoProvider;
69 this.gaugeMwPos = new HashMap<>();
70 this.gaugeMnwPos = new HashMap<>();
71 this.gaugeMhwPos = new HashMap<>();
72 this.gaugeHw5Pos = new HashMap<>();
73 } 56 }
74 57
75 /** 58 /**
76 * Calculate the salix line result rows 59 * Calculate the salix line result rows
77 */ 60 */
78 public void execute(final Calculation problems, final UINFOArtifact uinfo, final NavigableMap<Double, List<Double>> rangeScenarios, 61 public void execute(final Calculation problems, final UINFOArtifact uinfo, final NavigableMap<Double, List<Double>> rangeScenarios,
79 final ScenarioType scenarioType, final String[] scenarioLabels, final String rangeString, final String additionalString, 62 final ScenarioType scenarioType, final String[] scenarioLabels, final String rangeString, final String additionalString,
80 final SalixLineCalculationResults results) { 63 final SalixLineCalculationResults results) {
81 64
82 this.problems = problems; 65 final MainWstValuesCalculator mainWstValues = fetchGaugeMainValuePositions2(problems);
83 this.wst = WstValueTableFactory.getTable(this.riverInfoProvider.getRiver());
84
85 fetchGaugeMainValuePositions();
86 66
87 final WINFOArtifact winfo = new WinfoArtifactWrapper(uinfo); 67 final WINFOArtifact winfo = new WinfoArtifactWrapper(uinfo);
88 winfo.addStringData("ld_mode", "distance"); 68 winfo.addStringData("ld_mode", "distance");
89 winfo.addStringData("ld_step", "100"); 69 winfo.addStringData("ld_step", "100");
90 for (final double station : new ComputationRangeAccess(winfo).getKms()) { 70 for (final double station : new ComputationRangeAccess(winfo).getKms()) {
91 this.rows.add(createRow(station, rangeScenarios)); 71 this.rows.add(createRow(mainWstValues, station, rangeScenarios));
92 } 72 }
93 if (scenarioType == ScenarioType.REGIONAL) 73 if (scenarioType == ScenarioType.REGIONAL)
94 results.addResult(new SalixLineCalculationRegionalResult("Salix-regional", scenarioLabels, rangeString, additionalString, this.rows), problems); 74 results.addResult(new SalixLineCalculationRegionalResult("Salix-regional", scenarioLabels, rangeString, additionalString, this.rows), problems);
95 else if (scenarioType == ScenarioType.SUPRAREGIONAL) 75 else if (scenarioType == ScenarioType.SUPRAREGIONAL)
96 results.addResult(new SalixLineCalculationSupraRegionalResult("Salix-supra", scenarioLabels, rangeString, additionalString, this.rows), problems); 76 results.addResult(new SalixLineCalculationSupraRegionalResult("Salix-supra", scenarioLabels, rangeString, additionalString, this.rows), problems);
98 results.addResult(new SalixLineCalculationHistoricalResult("Salix-hist", scenarioLabels, rangeString, additionalString, this.rows), problems); 78 results.addResult(new SalixLineCalculationHistoricalResult("Salix-hist", scenarioLabels, rangeString, additionalString, this.rows), problems);
99 else 79 else
100 results.addResult(new SalixLineCalculationResult("Salix-simple", this.rows), problems); 80 results.addResult(new SalixLineCalculationResult("Salix-simple", this.rows), problems);
101 } 81 }
102 82
103 /** 83 private MainWstValuesCalculator fetchGaugeMainValuePositions2(final Calculation problems) {
104 * Fetch MQ, MNQ and MHQ of all gauges and determine the wst QPosition for each one 84 final MainWstValuesCalculator mainWstValues = MainWstValuesCalculator.forRiverInfo(this.riverInfoProvider, MAIN_VALUE_MQ, MAIN_VALUE_MNQ,
105 */ 85 MAIN_VALUE_MHQ, MAIN_VALUE_HQ5);
106 private void fetchGaugeMainValuePositions() { 86
107 this.gaugeMwPos.clear(); 87 if (!mainWstValues.hasPosition(MAIN_VALUE_MQ))
108 this.gaugeMnwPos.clear(); 88 problems.addProblem("uinfo_salix_calc.warning.missing_mq");
109 this.gaugeMhwPos.clear();
110 this.gaugeHw5Pos.clear();
111
112 this.firstGauge = null;
113 for (final Gauge gauge : this.riverInfoProvider.getGauges()) {
114 this.gaugeMwPos.put(gauge, null);
115 this.gaugeMnwPos.put(gauge, null);
116 this.gaugeMhwPos.put(gauge, null);
117 this.gaugeHw5Pos.put(gauge, null);
118 final double gaugeKm = gauge.getStation().doubleValue();
119 for (final MainValue mv : MainValue.getValuesOfGaugeAndType(gauge, MainValueTypeKey.Q)) {
120 if (mv.getMainValue().getName().equalsIgnoreCase("mq"))
121 this.gaugeMwPos.put(gauge, this.wst.getQPosition(gaugeKm, mv.getValue().doubleValue()));
122 else if (mv.getMainValue().getName().equalsIgnoreCase("mnq"))
123 this.gaugeMnwPos.put(gauge, this.wst.getQPosition(gaugeKm, mv.getValue().doubleValue()));
124 else if (mv.getMainValue().getName().equalsIgnoreCase("mhq"))
125 this.gaugeMhwPos.put(gauge, this.wst.getQPosition(gaugeKm, mv.getValue().doubleValue()));
126 else if (mv.getMainValue().getName().equalsIgnoreCase("hq5"))
127 this.gaugeHw5Pos.put(gauge, this.wst.getQPosition(gaugeKm, mv.getValue().doubleValue()));
128 }
129 if (this.firstGauge == null) {
130 this.refGaugeMwPos = this.gaugeMwPos.get(gauge);
131 this.refGaugeMnwPos = this.gaugeMnwPos.get(gauge);
132 this.refGaugeMhwPos = this.gaugeMhwPos.get(gauge);
133 this.refGaugeHw5Pos = this.gaugeHw5Pos.get(gauge);
134 this.firstGauge = gauge;
135 }
136 }
137 if (this.refGaugeMwPos == null)
138 this.problems.addProblem("uinfo_salix_calc.warning.missing_mq");
139 else { 89 else {
140 if (this.refGaugeMhwPos == null) 90 if (!mainWstValues.hasPosition(MAIN_VALUE_MHQ))
141 this.problems.addProblem("uinfo_salix_calc.warning.missing_mhq"); 91 problems.addProblem("uinfo_salix_calc.warning.missing_mhq");
142 if (this.refGaugeMnwPos == null) 92 if (!mainWstValues.hasPosition(MAIN_VALUE_MNQ))
143 this.problems.addProblem("uinfo_salix_calc.warning.missing_mnq"); 93 problems.addProblem("uinfo_salix_calc.warning.missing_mnq");
144 } 94 }
95
96 return mainWstValues;
145 } 97 }
146 98
147 /** 99 /**
148 * Create a result row for a station and its gauge, and add w-q-values as selected 100 * Create a result row for a station and its gauge, and add w-q-values as selected
149 */ 101 *
150 private ResultRow createRow(final double station, final NavigableMap<Double, List<Double>> rangeScenarios) { 102 * @param mainWstValues
103 */
104 private ResultRow createRow(final MainWstValuesCalculator mainWstValues, final double station, final NavigableMap<Double, List<Double>> rangeScenarios) {
151 105
152 final ResultRow row = ResultRow.create(); 106 final ResultRow row = ResultRow.create();
153 row.putValue(GeneralResultType.station, station); 107 row.putValue(GeneralResultType.station, station);
154 // Find station's gauge (obsolete version which calculates gauge-wise) 108 // Find station's gauge (obsolete version which calculates gauge-wise)
155 // final Gauge gauge = this.riverInfoProvider.getGauge(station, true); 109 // final Gauge gauge = this.riverInfoProvider.getGauge(station, true);
156 // Interpolate mnw, mw, and mhw 110 // Interpolate mnw, mw, and mhw
157 // final double mnw = interpolateW(station, this.gaugeMnwPos.get(gauge)); 111 // final double mnw = interpolateW(station, this.gaugeMnwPos.get(gauge));
158 // final double mw = interpolateW(station, this.gaugeMwPos.get(gauge)); 112 // final double mw = interpolateW(station, this.gaugeMwPos.get(gauge));
159 // final double mhw = interpolateW(station, this.gaugeMhwPos.get(gauge)); 113 // final double mhw = interpolateW(station, this.gaugeMhwPos.get(gauge));
160 final double mnw = interpolateW(station, this.refGaugeMnwPos); 114 final double mnw = mainWstValues.interpolateW(station, MAIN_VALUE_MNQ);
161 final double mw = interpolateW(station, this.refGaugeMwPos); 115 final double mw = mainWstValues.interpolateW(station, MAIN_VALUE_MQ);
162 final double mhw = interpolateW(station, this.refGaugeMhwPos); 116 final double mhw = mainWstValues.interpolateW(station, MAIN_VALUE_MHQ);
163 final double hw5 = interpolateW(station, this.refGaugeHw5Pos); 117 final double hw5 = mainWstValues.interpolateW(station, MAIN_VALUE_HQ5);
164 row.putValue(UInfoResultType.waterlevelMNW, mnw); 118 row.putValue(UInfoResultType.waterlevelMNW, mnw);
165 row.putValue(UInfoResultType.waterlevelMW, mw); 119 row.putValue(UInfoResultType.waterlevelMW, mw);
166 row.putValue(UInfoResultType.waterlevelMHW, mhw); 120 row.putValue(UInfoResultType.waterlevelMHW, mhw);
167 row.putValue(UInfoResultType.waterlevelMH5, hw5); 121 row.putValue(UInfoResultType.waterlevelMH5, hw5);
168 122
177 for (final Double deltaw : deltaws) { 131 for (final Double deltaw : deltaws) {
178 if (deltaw != null) { 132 if (deltaw != null) {
179 final double salix = calcSalix(mhw, mw, deltaw.doubleValue()); 133 final double salix = calcSalix(mhw, mw, deltaw.doubleValue());
180 final double scen = calcSalix(mhw, 0.0, deltaw.doubleValue()); 134 final double scen = calcSalix(mhw, 0.0, deltaw.doubleValue());
181 scenarios.add(new SalixScenario((int) (deltaw * 100), salix, scen)); 135 scenarios.add(new SalixScenario((int) (deltaw * 100), salix, scen));
182 } 136 } else {
183 else {
184 scenarios.add(null); 137 scenarios.add(null);
185 } 138 }
186 } 139 }
187 row.putValue(UInfoResultType.customMultiRowColSalixScenarios, scenarios); 140 row.putValue(UInfoResultType.customMultiRowColSalixScenarios, scenarios);
188 row.putValue(GeneralResultType.gaugeLabel, this.riverInfoProvider.findGauge(station)); 141 row.putValue(GeneralResultType.gaugeLabel, this.riverInfoProvider.findGauge(station));
189 return row; 142 return row;
190 }
191
192 /**
193 * Interpolates the W for a station with a fixed (virtual) wst column position
194 */
195 private double interpolateW(final double station, final QPosition qPosition) {
196 if (qPosition != null)
197 return this.wst.interpolateW(station, qPosition, this.problems);
198 return Double.NaN;
199 } 143 }
200 144
201 /** 145 /**
202 * Calculates the salix value 146 * Calculates the salix value
203 */ 147 */
261 205
262 // Search the station in the previously calculated result rows 206 // Search the station in the previously calculated result rows
263 final ResultRow stationRow = searchStation(station, result.getRows()); 207 final ResultRow stationRow = searchStation(station, result.getRows());
264 if (stationRow == null) 208 if (stationRow == null)
265 return Double.NaN; 209 return Double.NaN;
210
266 // Compute height from overflow duration days 211 // Compute height from overflow duration days
267 final List<VegetationZoneServerClientXChange> vzs = VegetationZoneServerClientXChange.getStandardList(null, null); // TODO river, context 212 final List<VegetationZoneServerClientXChange> vzs = VegetationZoneServerClientXChange.getStandardList(null, null); // TODO river, context
268 if ((vegetationZoneType >= 1) && (vegetationZoneType <= vzs.size())) { 213 if ((vegetationZoneType >= 1) && (vegetationZoneType <= vzs.size())) {
269 final int uefd = vzs.get(vegetationZoneType - 1).getMin_day_overflow(); 214 final int uefd = vzs.get(vegetationZoneType - 1).getMin_day_overflow();
270 // Üfd = -70,559 ∗ ln((DGM - MW) + 0,5) + 80,711 215 // Üfd = -70,559 ∗ ln((DGM - MW) + 0,5) + 80,711

http://dive4elements.wald.intevation.org