Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/uinfo/salix/SalixLineCalculation.java @ 9394:439699ff9b2d
Added U-Info iota (prev. salix) calculation for historical scenario
author | mschaefer |
---|---|
date | Fri, 10 Aug 2018 17:31:46 +0200 |
parents | 2da486c7c05f |
children | 6e7094368e97 |
comparison
equal
deleted
inserted
replaced
9393:6174daaf5e56 | 9394:439699ff9b2d |
---|---|
8 * documentation coming with Dive4Elements River for details. | 8 * documentation coming with Dive4Elements River for details. |
9 */ | 9 */ |
10 package org.dive4elements.river.artifacts.uinfo.salix; | 10 package org.dive4elements.river.artifacts.uinfo.salix; |
11 | 11 |
12 import java.util.ArrayList; | 12 import java.util.ArrayList; |
13 import java.util.Collection; | |
13 import java.util.List; | 14 import java.util.List; |
14 import java.util.NavigableMap; | 15 import java.util.NavigableMap; |
15 import java.util.TreeMap; | 16 import java.util.TreeMap; |
16 | 17 |
17 import org.apache.commons.lang.math.DoubleRange; | 18 import org.apache.commons.lang.math.DoubleRange; |
20 import org.dive4elements.river.artifacts.common.GeneralResultType; | 21 import org.dive4elements.river.artifacts.common.GeneralResultType; |
21 import org.dive4elements.river.artifacts.model.Calculation; | 22 import org.dive4elements.river.artifacts.model.Calculation; |
22 import org.dive4elements.river.artifacts.model.CalculationResult; | 23 import org.dive4elements.river.artifacts.model.CalculationResult; |
23 import org.dive4elements.river.artifacts.resources.Resources; | 24 import org.dive4elements.river.artifacts.resources.Resources; |
24 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; | 25 import org.dive4elements.river.artifacts.sinfo.common.RiverInfoProvider; |
26 import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsFinder; | |
27 import org.dive4elements.river.artifacts.sinfo.tkhstate.BedHeightsUtils; | |
28 import org.dive4elements.river.artifacts.sinfo.tkhstate.DefaultBedHeights; | |
25 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; | 29 import org.dive4elements.river.artifacts.sinfo.util.CalculationUtils; |
26 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; | 30 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo; |
27 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; | 31 import org.dive4elements.river.artifacts.uinfo.UINFOArtifact; |
28 import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; | 32 import org.dive4elements.river.artifacts.uinfo.salix.SalixLineAccess.ScenarioType; |
33 import org.dive4elements.river.model.BedHeight; | |
29 import org.dive4elements.river.model.River; | 34 import org.dive4elements.river.model.River; |
35 import org.dive4elements.river.utils.Formatter; | |
30 | 36 |
31 /** | 37 /** |
38 * Calculation of a iota (former salix) longitudinal section, optionally with a delta scenario | |
39 * | |
32 * @author Domenico Nardi Tironi | 40 * @author Domenico Nardi Tironi |
41 * @author Matthias Schäfer | |
33 * | 42 * |
34 */ | 43 */ |
35 final class SalixLineCalculation { | 44 final class SalixLineCalculation { |
36 | 45 |
37 private final CallContext context; | 46 private final CallContext context; |
38 | 47 |
48 private Calculation problems; | |
49 | |
39 public SalixLineCalculation(final CallContext context) { | 50 public SalixLineCalculation(final CallContext context) { |
40 this.context = context; | 51 this.context = context; |
41 } | 52 } |
42 | 53 |
54 /** | |
55 * Calculates the iota longitudinal section and delta scenario of a uinfo artifact | |
56 */ | |
43 public CalculationResult calculate(final UINFOArtifact uinfo) { | 57 public CalculationResult calculate(final UINFOArtifact uinfo) { |
44 final Calculation problems = new Calculation(); | 58 this.problems = new Calculation(); |
45 | 59 |
46 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name()); | 60 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), uinfo.getCalculationMode().name()); |
47 final String user = CalculationUtils.findArtifactUser(this.context, uinfo); | 61 final String user = CalculationUtils.findArtifactUser(this.context, uinfo); |
48 | 62 |
49 final SalixLineAccess accessSalix = new SalixLineAccess(uinfo); | 63 final SalixLineAccess accessSalix = new SalixLineAccess(uinfo); |
60 final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range); | 74 final SalixLineCalculationResults results = new SalixLineCalculationResults(calcModeLabel, user, riverInfo, range); |
61 | 75 |
62 final SalixLineCalculator calculator = new SalixLineCalculator(riverInfoProvider); | 76 final SalixLineCalculator calculator = new SalixLineCalculator(riverInfoProvider); |
63 final NavigableMap<Double, List<Double>> rangeScenarios = buildRangeScenarios(accessSalix); | 77 final NavigableMap<Double, List<Double>> rangeScenarios = buildRangeScenarios(accessSalix); |
64 | 78 |
65 calculator.execute(problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix), | 79 calculator.execute(this.problems, uinfo, rangeScenarios, scenarioType, buildScenarioLabels(accessSalix), buildPartialRangeString(accessSalix), |
66 buildAdditionalString(accessSalix), results); | 80 buildAdditionalString(accessSalix), results); |
67 | 81 |
68 return new CalculationResult(results, problems); | 82 return new CalculationResult(results, this.problems); |
69 } | 83 } |
70 | 84 |
71 /** | 85 /** |
72 * Build a map of delta-Ws by from-km for the selected scenario | 86 * Builds a map of delta-Ws by from-km for the selected scenario |
73 */ | 87 */ |
74 private NavigableMap<Double, List<Double>> buildRangeScenarios(final SalixLineAccess access) { | 88 private NavigableMap<Double, List<Double>> buildRangeScenarios(final SalixLineAccess access) { |
75 final NavigableMap<Double, List<Double>> rangeScenarios = new TreeMap<>(); | 89 final NavigableMap<Double, List<Double>> rangeScenarios = new TreeMap<>(); |
76 if (access.getScenario() == ScenarioType.REGIONAL) | 90 if (access.getScenario() == ScenarioType.REGIONAL) |
77 fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(), | 91 fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(), |
78 access.getRegionalScenarioIntegers()); | 92 access.getRegionalScenarioIntegers()); |
79 else if (access.getScenario() == ScenarioType.SUPRAREGIONAL) | 93 else if (access.getScenario() == ScenarioType.SUPRAREGIONAL) |
80 fillRangeScenarios(rangeScenarios, access.getSupraRegionalString()); | 94 fillRangeScenarios(rangeScenarios, access.getSupraRegionalString()); |
81 // TODO else if (access.getScenario().equals(ScenarioType.HISTORICAL.getKey())) | 95 else if (access.getScenario() == ScenarioType.HISTORICAL) |
82 // historisches Szenario aus MSH etc. | 96 fillRangeScenarios(rangeScenarios, access, access.getFromPart().doubleValue(), access.getToPart().doubleValue(), access.getBedHeightId()); |
83 else | 97 else |
84 fillRangeScenarios(rangeScenarios, access); | 98 fillRangeScenarios(rangeScenarios, access); |
85 | 99 |
86 return rangeScenarios; | 100 return rangeScenarios; |
87 } | 101 } |
88 | 102 |
89 /** | 103 /** |
90 * Fill a map of delta-Ws with only one 0-delta for the whole calc range (no scenario) | 104 * Fills a map of delta-Ws with only one 0-delta for the whole calc range (no scenario) |
91 */ | 105 */ |
92 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange) { | 106 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange) { |
93 final List<Double> nulls = new ArrayList<>(); | 107 final List<Double> nulls = new ArrayList<>(); |
94 nulls.add(0.0); | 108 nulls.add(null); |
95 rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); | 109 rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); |
96 } | 110 } |
97 | 111 |
98 /** | 112 /** |
99 * Fill a map of delta-Ws by km-range from the regional scenario input data | 113 * Fills a map of delta-Ws by km-range from the regional scenario input data |
100 */ | 114 */ |
101 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, final double partFrom, | 115 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, |
102 final double partTo, final int[] deltaWs) { | 116 final double partFrom, final double partTo, final int[] deltaWs) { |
103 final List<Double> nulls = new ArrayList<>(); | 117 final List<Double> nulls = new ArrayList<>(); |
104 final List<Double> dwsm = new ArrayList<>(); | 118 final List<Double> dwsm = new ArrayList<>(); |
105 for (int i = 0; i <= deltaWs.length - 1; i++) { | 119 for (int i = 0; i <= deltaWs.length - 1; i++) { |
106 nulls.add(0.0); | 120 nulls.add(null); |
107 dwsm.add(deltaWs[i] / 100.0); | 121 dwsm.add(deltaWs[i] / 100.0); |
108 } | 122 } |
109 rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); | 123 rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); |
110 rangeScenarios.put(Double.valueOf(partFrom - 0.0001), dwsm); | 124 rangeScenarios.put(Double.valueOf(partFrom - 0.0001), dwsm); |
111 rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls); | 125 rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls); |
112 } | 126 } |
113 | 127 |
114 /** | 128 /** |
115 * Fill a map of delta-Ws by km-range from the supraregional scenario input data | 129 * Fills a map of delta-Ws by km-range from the supraregional scenario input data |
116 * (the zones input by the user cover the calc range completely) | 130 * (the zones input by the user cover the calc range completely) |
117 */ | 131 */ |
118 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final String zones) { | 132 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final String zones) { |
119 final List<SalixZone> parts = SalixZone.parse(zones); | 133 final List<SalixZone> parts = SalixZone.parse(zones); |
120 for (final SalixZone part : parts) { | 134 for (final SalixZone part : parts) { |
121 final List<Double> dwsm = new ArrayList<>(); | 135 final List<Double> dwsm = new ArrayList<>(); |
122 dwsm.add(part.getDwsplValue() / 100.0); | 136 if (part.getDwsplValue() == 0) |
137 dwsm.add(null); | |
138 else | |
139 dwsm.add(part.getDwsplValue() / 100.0); | |
123 rangeScenarios.put(Double.valueOf(part.getFromKm().doubleValue() - 0.0001), dwsm); | 140 rangeScenarios.put(Double.valueOf(part.getFromKm().doubleValue() - 0.0001), dwsm); |
124 } | 141 } |
125 } | 142 } |
126 | 143 |
127 /** | 144 /** |
128 * Build the list of delta-w labels for the scenario type | 145 * Fetches historical and reference bed heights and fills a map of delta-MSHs for all fetched stations in the calc range |
146 */ | |
147 private void fillRangeScenarios(final NavigableMap<Double, List<Double>> rangeScenarios, final RangeAccess calcRange, | |
148 final double partFrom, final double partTo, final int historicalBedHeightId) { | |
149 | |
150 // Find relevant default bed-heights | |
151 final River river = calcRange.getRiver(); | |
152 final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(this.problems); | |
153 if (defaultBedHeights.isEmpty()) | |
154 return; | |
155 final DoubleRange scenarioRange = new DoubleRange(partFrom, partTo); | |
156 final Collection<BedHeightsFinder> allFinders = BedHeightsFinder.createTkhBedHeights(this.problems, scenarioRange, defaultBedHeights); | |
157 final Collection<BedHeightsFinder> currentFinders = new ArrayList<>(allFinders); | |
158 | |
159 // Add historical bed-heights | |
160 final BedHeightsFinder historicalFinder = BedHeightsFinder.forId(this.problems, historicalBedHeightId, scenarioRange); | |
161 allFinders.add(historicalFinder); | |
162 final Collection<Double> stations = BedHeightsUtils.extractStationCollection(allFinders, true); | |
163 final List<Double> nulls = new ArrayList<>(); | |
164 nulls.add(null); | |
165 rangeScenarios.put(Double.valueOf(calcRange.getLowerKm() - 0.0001), nulls); | |
166 for (final Double station : stations) { | |
167 rangeScenarios.put(station, new ArrayList<Double>()); | |
168 rangeScenarios.get(station).add(Double.valueOf(bedHeightDifference(station.doubleValue(), currentFinders, historicalFinder))); | |
169 } | |
170 rangeScenarios.put(Double.valueOf(partTo + 0.0001), nulls); | |
171 } | |
172 | |
173 /** | |
174 * Gets the difference of a historical bed height against a current one for a station | |
175 */ | |
176 private double bedHeightDifference(final double station, final Collection<BedHeightsFinder> currentFinders, final BedHeightsFinder historicalFinder) { | |
177 double currentMSH = Double.NaN; | |
178 for (final BedHeightsFinder bhf : currentFinders) { | |
179 currentMSH = bhf.getMeanBedHeight(station); | |
180 if (!Double.isNaN(currentMSH)) | |
181 break; | |
182 } | |
183 return Formatter.roundFlowDepth(historicalFinder.getMeanBedHeight(station)).subtract(Formatter.roundFlowDepth(currentMSH)).doubleValue(); | |
184 } | |
185 | |
186 /** | |
187 * Builds the list of delta-w labels for the scenario type | |
129 */ | 188 */ |
130 private String[] buildScenarioLabels(final SalixLineAccess access) { | 189 private String[] buildScenarioLabels(final SalixLineAccess access) { |
131 final List<String> labels = new ArrayList<>(); | 190 final List<String> labels = new ArrayList<>(); |
132 if (access.getScenario() == ScenarioType.REGIONAL) { | 191 if (access.getScenario() == ScenarioType.REGIONAL) { |
133 final int[] deltaws = access.getRegionalScenarioIntegers(); | 192 final int[] deltaws = access.getRegionalScenarioIntegers(); |
140 labels.add(Resources.getMsg(this.context.getMeta(), "uinfo_salix_scenario_historical")); | 199 labels.add(Resources.getMsg(this.context.getMeta(), "uinfo_salix_scenario_historical")); |
141 return labels.toArray(new String[labels.size()]); | 200 return labels.toArray(new String[labels.size()]); |
142 } | 201 } |
143 | 202 |
144 /** | 203 /** |
145 * Build the km range string for the scenario type | 204 * Builds the km range string for the scenario type |
146 */ | 205 */ |
147 private String buildPartialRangeString(final SalixLineAccess access) { | 206 private String buildPartialRangeString(final SalixLineAccess access) { |
148 if ((access.getScenario() == ScenarioType.REGIONAL) || (access.getScenario() == ScenarioType.HISTORICAL)) { | 207 if ((access.getScenario() == ScenarioType.REGIONAL) || (access.getScenario() == ScenarioType.HISTORICAL)) { |
149 return String.format("%s - %s", GeneralResultType.station.exportValue(this.context, access.getFromPart().doubleValue()), | 208 return String.format("%s - %s", GeneralResultType.station.exportValue(this.context, access.getFromPart().doubleValue()), |
150 GeneralResultType.station.exportValue(this.context, access.getToPart().doubleValue())); | 209 GeneralResultType.station.exportValue(this.context, access.getToPart().doubleValue())); |
164 } | 223 } |
165 return ""; | 224 return ""; |
166 } | 225 } |
167 | 226 |
168 /** | 227 /** |
169 * Build the delta w or time string for the scenario type | 228 * Builds the delta w or time string for the scenario type |
170 */ | 229 */ |
171 private String buildAdditionalString(final SalixLineAccess access) { | 230 private String buildAdditionalString(final SalixLineAccess access) { |
172 if (access.getScenario() == ScenarioType.REGIONAL) { | 231 if (access.getScenario() == ScenarioType.REGIONAL) { |
173 String deltas = ""; | 232 String deltas = ""; |
174 String sep = ""; | 233 String sep = ""; |