Mercurial > dive4elements > river
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 |