comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhstate/TkhCalculation.java @ 8964:45f1ad66560e

Code cleanup concerning calculations: improved error handling; improved interpolation; bed heights are now always used for spatial discretisation
author gernotbelger
date Thu, 29 Mar 2018 15:48:17 +0200
parents 183f42641ab6
children b5600453bb8f
comparison
equal deleted inserted replaced
8963:b98fbd91f64a 8964:45f1ad66560e
14 import java.util.HashMap; 14 import java.util.HashMap;
15 import java.util.List; 15 import java.util.List;
16 import java.util.Map; 16 import java.util.Map;
17 import java.util.Map.Entry; 17 import java.util.Map.Entry;
18 import java.util.Set; 18 import java.util.Set;
19 import java.util.TreeSet;
19 20
20 import org.apache.commons.lang.math.DoubleRange; 21 import org.apache.commons.lang.math.DoubleRange;
21 import org.apache.commons.lang.math.NumberRange; 22 import org.apache.commons.lang.math.NumberRange;
22 import org.dive4elements.artifacts.CallContext; 23 import org.dive4elements.artifacts.CallContext;
23 import org.dive4elements.river.artifacts.WINFOArtifact; 24 import org.dive4elements.river.artifacts.WINFOArtifact;
63 64
64 final Calculation problems = new Calculation(); 65 final Calculation problems = new Calculation();
65 66
66 /* find relevant bed-heights */ 67 /* find relevant bed-heights */
67 final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(problems); 68 final List<BedHeight> defaultBedHeights = new DefaultBedHeights(river).getBedHeights(problems);
68 final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(calcRange, defaultBedHeights); 69 final Collection<BedHeightsFinder> bedHeights = BedHeightsFinder.createTkhBedHeights(problems, calcRange, defaultBedHeights);
69 70
70 /* misuse winfo-artifact to calculate waterlevels in the same way */ 71 /* misuse winfo-artifact to calculate waterlevels in the same way */
71 final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo); 72 final WINFOArtifact winfo = new WinfoArtifactWrapper(sinfo);
72 73
73 /* calculate waterlevels */ 74 /* calculate waterlevels */
83 final String descriptionHeader = descBuilder.getColumnHeader(); 84 final String descriptionHeader = descBuilder.getColumnHeader();
84 85
85 /* for each waterlevel, do a tkh calculation */ 86 /* for each waterlevel, do a tkh calculation */
86 final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange, descriptionHeader); 87 final TkhCalculationResults results = new TkhCalculationResults(calcModeLabel, user, riverInfo, calcRange, descriptionHeader);
87 88
89 /* determine calculation steps */
90 final Collection<Double> allStations = determineCalculationSteps(bedHeights);
91
88 for (final WQKms wqKms : kms) { 92 for (final WQKms wqKms : kms) {
89 93 final TkhCalculationResult result = calculateResult(calcRange, allStations, infoProvider, wqKms, bedHeights, descBuilder, problems);
90 final TkhCalculationResult result = calculateResult(calcRange, infoProvider, wqKms, bedHeights, descBuilder, problems);
91 if (result != null) 94 if (result != null)
92 // FIXME: must be sorted by station!
93 results.addResult(result); 95 results.addResult(result);
94 } 96 }
95 97
96 return new CalculationResult(results, problems); 98 return new CalculationResult(results, problems);
99 }
100
101 /**
102 * Calculation steps are simply the union of all stations of all involved bed-height datasets
103 */
104 private Collection<Double> determineCalculationSteps(final Collection<BedHeightsFinder> bedHeights) {
105
106 final Collection<Double> allStations = new TreeSet<>();
107
108 for (final BedHeightsFinder bedHeight : bedHeights) {
109 final Collection<Double> stations = bedHeight.getStations();
110 allStations.addAll(stations);
111 }
112
113 return allStations;
97 } 114 }
98 115
99 private WQKms[] calculateWaterlevels(final WINFOArtifact winfo, final Calculation problems) { 116 private WQKms[] calculateWaterlevels(final WINFOArtifact winfo, final Calculation problems) {
100 117
101 final CalculationResult waterlevelData = winfo.getWaterlevelData(this.context); 118 final CalculationResult waterlevelData = winfo.getWaterlevelData(this.context);
110 } 127 }
111 128
112 return (WQKms[]) waterlevelData.getData(); 129 return (WQKms[]) waterlevelData.getData();
113 } 130 }
114 131
115 private TkhCalculationResult calculateResult(final DoubleRange calcRange, final RiverInfoProvider riverInfo, final WQKms wkms, 132 private TkhCalculationResult calculateResult(final DoubleRange calcRange, final Collection<Double> allStations, final RiverInfoProvider riverInfo,
116 final Collection<BedHeightsFinder> bedHeights, final WaterlevelDescriptionBuilder descBuilder, final Calculation problems) { 133 final WQKms wkms, final Collection<BedHeightsFinder> bedHeights, final WaterlevelDescriptionBuilder descBuilder, final Calculation problems) {
117 134
118 // FIXME: wo kommt das her? via winfo kein jahr vorhanden, oder doch? aber soll in metadaten ausgegeben werden... 135 // We have no wst year as the wst is created by a calculation; we do not need it though
119 final int wspYear = -1; 136 final int wspYear = -1;
120 // FIXME: richtig? vgl. WInfo? 137 // Remark: showAllGauges only true for Fixierungsanalyse, false for WInfo, so false here as well
121 final boolean showAllGauges = false; 138 final boolean showAllGauges = false;
122 final WaterlevelData waterlevel = new WaterlevelData(wkms, wspYear, showAllGauges); 139 final WaterlevelData waterlevel = new WaterlevelData(wkms, wspYear, showAllGauges);
123 140
124 final RiverInfoProvider riverInfoProvider = riverInfo.forWaterlevel(waterlevel); 141 final RiverInfoProvider riverInfoProvider = riverInfo.forWaterlevel(waterlevel);
125 142
135 return null; 152 return null;
136 } 153 }
137 154
138 final Collection<SInfoResultRow> rows = new ArrayList<>(); 155 final Collection<SInfoResultRow> rows = new ArrayList<>();
139 156
140 /* using wst-kms as basis, because we know that they are generated wst's with a fixed km-step */ 157 for (final Double stationDbl : allStations) {
141 // FIXME: das führt dazu, das aktuell die Sohlhöhen beliebig linear interpolierrt werden. ist das immer richtig? z.b. 158
142 // bei großen abständen? 159 final double station = stationDbl;
143
144 final int size = wkms.size();
145 for (int i = 0; i < size; i++) {
146
147 final double station = wkms.getKm(i);
148 160
149 /* find the right calculator (i.e. bed height) depending on station, there should only be one maximal */ 161 /* find the right calculator (i.e. bed height) depending on station, there should only be one maximal */
150 final TkhCalculator tkhCalculator = findCalculator(calculatorsByRanges, station); 162 final TkhCalculator tkhCalculator = findCalculator(calculatorsByRanges, station);
151 if (tkhCalculator == null) 163 if (tkhCalculator == null)
152 continue; 164 continue;
186 198
187 final BedHeightInfo info = bedHeightsProvider.getInfo(); 199 final BedHeightInfo info = bedHeightsProvider.getInfo();
188 200
189 final NumberRange range = new NumberRange(info.getFrom(), info.getTo()); 201 final NumberRange range = new NumberRange(info.getFrom(), info.getTo());
190 202
191 final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(wkms); 203 final WaterlevelValuesFinder waterlevelProvider = WaterlevelValuesFinder.fromKms(problems, wkms);
192 final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms); 204 final DischargeValuesFinder dischargeProvider = DischargeValuesFinder.fromKms(wkms);
193 205
194 /* initialize tkh calculator */ 206 /* initialize tkh calculator */
195 final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, this.context, problems, wstLabel, riverInfoProvider.getRiver(), 207 final TkhCalculator tkhCalculator = TkhCalculator.buildTkhCalculator(true, problems, wstLabel, riverInfoProvider.getRiver(), calcRange,
196 calcRange, waterlevelProvider, dischargeProvider, bedHeightsProvider); 208 waterlevelProvider, dischargeProvider, bedHeightsProvider);
197 209
198 if (tkhCalculator != null) { 210 if (tkhCalculator.hasTkh()) {
199 /* just ignore null ones, problems have already been updated by buildTkhCalculator() */ 211 /* just ignore invalid ones, problems have already been updated by buildTkhCalculator() */
200 calculatorByRanges.put(range, tkhCalculator); 212 calculatorByRanges.put(range, tkhCalculator);
201 } 213 }
202 } 214 }
203 215
204 return calculatorByRanges; 216 return calculatorByRanges;

http://dive4elements.wald.intevation.org