comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java @ 8894:a66f2a7c4f84

SINFO FlowDepth - slight code cleanup
author gernotbelger
date Thu, 15 Feb 2018 18:40:40 +0100
parents f431aec10d2c
children b6f7961e4cc5
comparison
equal deleted inserted replaced
8893:ffebc94cf679 8894:a66f2a7c4f84
14 import java.util.Collection; 14 import java.util.Collection;
15 import java.util.Collections; 15 import java.util.Collections;
16 import java.util.Date; 16 import java.util.Date;
17 import java.util.List; 17 import java.util.List;
18 18
19 import org.apache.commons.lang.math.DoubleRange;
19 import org.apache.commons.math.FunctionEvaluationException; 20 import org.apache.commons.math.FunctionEvaluationException;
20 import org.apache.commons.math.analysis.UnivariateRealFunction; 21 import org.apache.commons.math.analysis.UnivariateRealFunction;
21 import org.dive4elements.artifacts.ArtifactDatabase; 22 import org.dive4elements.artifacts.ArtifactDatabase;
22 import org.dive4elements.artifacts.CallContext; 23 import org.dive4elements.artifacts.CallContext;
23 import org.dive4elements.river.artifacts.BedHeightsArtifact; 24 import org.dive4elements.river.artifacts.BedHeightsArtifact;
29 import org.dive4elements.river.artifacts.model.minfo.QualityMeasurementFactory; 30 import org.dive4elements.river.artifacts.model.minfo.QualityMeasurementFactory;
30 import org.dive4elements.river.artifacts.model.minfo.QualityMeasurements; 31 import org.dive4elements.river.artifacts.model.minfo.QualityMeasurements;
31 import org.dive4elements.river.artifacts.resources.Resources; 32 import org.dive4elements.river.artifacts.resources.Resources;
32 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; 33 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact;
33 import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthAccess.DifferencesPair; 34 import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthAccess.DifferencesPair;
35 import org.dive4elements.river.artifacts.sinfo.util.BedHeightInfo;
36 import org.dive4elements.river.artifacts.sinfo.util.RiverInfo;
37 import org.dive4elements.river.artifacts.sinfo.util.WstInfo;
34 import org.dive4elements.river.artifacts.states.WaterlevelData; 38 import org.dive4elements.river.artifacts.states.WaterlevelData;
35 import org.dive4elements.river.artifacts.states.WaterlevelFetcher; 39 import org.dive4elements.river.artifacts.states.WaterlevelFetcher;
36 import org.dive4elements.river.model.BedHeight; 40 import org.dive4elements.river.model.BedHeight;
37 import org.dive4elements.river.model.BedHeightValue; 41 import org.dive4elements.river.model.BedHeightValue;
38 import org.dive4elements.river.model.Gauge; 42 import org.dive4elements.river.model.Gauge;
63 final String user = database.findArtifactUser(sinfo.identifier()); 67 final String user = database.findArtifactUser(sinfo.identifier());
64 68
65 /* access input data */ 69 /* access input data */
66 final FlowDepthAccess access = new FlowDepthAccess(sinfo); 70 final FlowDepthAccess access = new FlowDepthAccess(sinfo);
67 final River river = access.getRiver(); 71 final River river = access.getRiver();
72 final RiverInfo riverInfo = new RiverInfo(river);
68 73
69 final Collection<DifferencesPair> diffPairs = access.getDifferencePairs(); 74 final Collection<DifferencesPair> diffPairs = access.getDifferencePairs();
70 75
71 final double from = access.getFrom(); 76 final double from = access.getFrom();
72 final double to = access.getTo(); 77 final double to = access.getTo();
78 final DoubleRange calcRange = new DoubleRange(from, to);
73 79
74 final boolean useTkh = access.isUseTransportBodies(); 80 final boolean useTkh = access.isUseTransportBodies();
75 81
76 /* calculate results for each diff pair */ 82 /* calculate results for each diff pair */
77 final Calculation problems = new Calculation(); 83 final Calculation problems = new Calculation();
79 final List<Gauge> gauges = river.determineGauges(from, to); 85 final List<Gauge> gauges = river.determineGauges(from, to);
80 final GaugeIndex gaugeIndex = new GaugeIndex(gauges); 86 final GaugeIndex gaugeIndex = new GaugeIndex(gauges);
81 87
82 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name()); 88 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name());
83 89
84 final FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, river, from, to, useTkh); 90 final FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, riverInfo, calcRange, useTkh);
85 91
86 for (final DifferencesPair diffPair : diffPairs) { 92 for (final DifferencesPair diffPair : diffPairs) {
87 final FlowDepthCalculationResult result = calculateResult(river, from, to, diffPair, problems, gaugeIndex); 93 final FlowDepthCalculationResult result = calculateResult(river, calcRange, diffPair, problems, gaugeIndex);
88 if (result != null) 94 if (result != null)
89 results.addResult(result); 95 results.addResult(result);
90 } 96 }
91 97
92 return new CalculationResult(results, problems); 98 return new CalculationResult(results, problems);
93 } 99 }
94 100
95 private FlowDepthCalculationResult calculateResult(final River river, final double from, final double to, final DifferencesPair diffPair, 101 private FlowDepthCalculationResult calculateResult(final River river, final DoubleRange calcRange, final DifferencesPair diffPair,
96 final Calculation problems, final GaugeIndex gaugeIndex) { 102 final Calculation problems, final GaugeIndex gaugeIndex) {
97 103
98 /* access real input data from database */ 104 /* access real input data from database */
99 final String soundingId = diffPair.getSoundingId(); 105 final String soundingId = diffPair.getSoundingId();
100 final String wstId = diffPair.getWstId(); 106 final String wstId = diffPair.getWstId();
101 107
102 final BedHeight bedHeight = loadBedHeight(soundingId, from, to); 108 final BedHeight bedHeight = loadBedHeight(soundingId);
103 if (bedHeight == null) { 109 if (bedHeight == null) {
104 final String message = Resources.format(this.context.getMeta(), "Failed to access sounding with id '{0}'", soundingId); 110 final String message = Resources.format(this.context.getMeta(), "Failed to access sounding with id '{0}'", soundingId);
105 problems.addProblem(message); 111 problems.addProblem(message);
106 return null; 112 return null;
107 } 113 }
118 final String wspLabel = wstKms.getName(); 124 final String wspLabel = wstKms.getName();
119 final String soundingLabel = bedHeight.getDescription(); 125 final String soundingLabel = bedHeight.getDescription();
120 final String label = String.format("%s - %s", wspLabel, soundingLabel); 126 final String label = String.format("%s - %s", wspLabel, soundingLabel);
121 127
122 checkYearDifference(label, waterlevel, bedHeight, problems); 128 checkYearDifference(label, waterlevel, bedHeight, problems);
123 checkWaterlevelDiscretisation(wstKms, problems); 129 checkWaterlevelDiscretisation(wstKms, calcRange, problems);
130 // TODO: prüfen, ob sohlhöen die calcRange abdecken/überschneiden
124 131
125 /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */ 132 /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */
126 final String notinrange = Resources.getMsg(this.context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE); 133 final String notinrange = Resources.getMsg(this.context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE);
127 134
128 final Gauge refGauge = waterlevel.findReferenceGauge(river); 135 final Gauge refGauge = waterlevel.findReferenceGauge(river);
140 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingQ", null, label); 147 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingQ", null, label);
141 problems.addProblem(message); 148 problems.addProblem(message);
142 // TODO: keine Berechnung TKH 149 // TODO: keine Berechnung TKH
143 } 150 }
144 151
145 final QualityMeasurements bedMeasurements = getBedMeasurements(river, from, to, sounding.getYear()); 152 final QualityMeasurements bedMeasurements = getBedMeasurements(river, calcRange, sounding.getYear());
146 // FIXME: prüfung ob (genug) werte vorhanden sind? was sind genau die kriterien? falls nein, problemhinzufügen und keine 153 // FIXME: prüfung ob (genug) werte vorhanden sind? was sind genau die kriterien? falls nein, problemhinzufügen und keine
147 // berechnung tkh 154 // berechnung tkh
148 // FIXME: wie wird ggf. interpoliert? --> absprache? 155 // FIXME: wie wird ggf. interpoliert? --> absprache?
149 // FIXME: mir direkt aufgefallen, die Beispieldatenbank liefert Werte zum gleichen km und zeitpunkt, die messwerte sind 156 // FIXME: mir direkt aufgefallen, die Beispieldatenbank liefert Werte zum gleichen km und zeitpunkt, die messwerte sind
150 // aber unterschiedlich....??? 157 // aber unterschiedlich....???
163 final List<BedHeightValue> values = bedHeight.getValues(); 170 final List<BedHeightValue> values = bedHeight.getValues();
164 171
165 final List<BedHeightValue> sortedValues = new ArrayList<>(values); 172 final List<BedHeightValue> sortedValues = new ArrayList<>(values);
166 Collections.sort(sortedValues, new BedHeightStationComparator()); 173 Collections.sort(sortedValues, new BedHeightStationComparator());
167 174
168 SoilKind lastKind = SoilKind.mobil; 175 SoilKind lastKind = SoilKind.starr;
169 176
170 for (final BedHeightValue bedHeightValue : sortedValues) { 177 for (final BedHeightValue bedHeightValue : sortedValues) {
171 178
172 final Double station = bedHeightValue.getStation(); 179 final Double station = bedHeightValue.getStation();
173 if (station == null || station.isNaN()) 180 if (station == null || station.isNaN())
178 continue; 185 continue;
179 186
180 final double km = station; 187 final double km = station;
181 final double meanBedHeight = meanBedHeightDbl; 188 final double meanBedHeight = meanBedHeightDbl;
182 189
190 if (!calcRange.containsDouble(km))
191 continue;
192
183 try { 193 try {
184 // FIXME: check out of range 194 // FIXME: check out of range
185 final double wst = wstInterpolator.value(km); 195 final double wst = wstInterpolator.value(km);
186 196
187 final double flowDepth = wst - meanBedHeight; 197 final double flowDepth = wst - meanBedHeight;
191 final double discharge = Double.NaN; 201 final double discharge = Double.NaN;
192 202
193 // FIXME: calculate tkh 203 // FIXME: calculate tkh
194 204
195 // REMARK: bissl spielerei zum testen damit die sohlart nicht zu schnell wechselt 205 // REMARK: bissl spielerei zum testen damit die sohlart nicht zu schnell wechselt
196 final boolean changeKind = Math.random() > 0.95; 206 final boolean changeKind = false; // Math.random() > 0.95;
197 SoilKind kind; 207 SoilKind kind;
198 if (changeKind) { 208 if (changeKind) {
199 switch (lastKind) { 209 switch (lastKind) {
200 case starr: 210 case starr:
201 kind = SoilKind.mobil; 211 kind = SoilKind.mobil;
229 tkhUp = tkh / 2; 239 tkhUp = tkh / 2;
230 tkhDown = -tkh / 2; 240 tkhDown = -tkh / 2;
231 break; 241 break;
232 } 242 }
233 243
234
235 // REMARK: access the location once only during calculation 244 // REMARK: access the location once only during calculation
236 final String location = LocationProvider.getLocation(river.getName(), km); 245 final String location = LocationProvider.getLocation(river.getName(), km);
237 246
238 // REMARK: access the gauge once only during calculation 247 // REMARK: access the gauge once only during calculation
239 final Gauge gauge = findGauge(waterlevel, refGauge, gaugeIndex, km); 248 final Gauge gauge = findGauge(waterlevel, refGauge, gaugeIndex, km);
256 265
257 /** 266 /**
258 * Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb) 267 * Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb)
259 * Abhängig von Peiljahr 268 * Abhängig von Peiljahr
260 */ 269 */
261 private QualityMeasurements getBedMeasurements(final River river, final double from, final double to, final int soundingYear) { 270 private QualityMeasurements getBedMeasurements(final River river, final DoubleRange calcRange, final Integer soundingYear) {
262 271
263 /* construct valid measurement time range */ 272 /* construct valid measurement time range */
264 final Calendar cal = Calendar.getInstance(); 273 final Calendar cal = Calendar.getInstance();
265 cal.clear(); 274 cal.clear();
266 275
268 final Date startTime = cal.getTime(); 277 final Date startTime = cal.getTime();
269 278
270 cal.set(soundingYear + VALID_BED_MEASUREMENT_YEARS, 11, 31); 279 cal.set(soundingYear + VALID_BED_MEASUREMENT_YEARS, 11, 31);
271 final Date endTime = cal.getTime(); 280 final Date endTime = cal.getTime();
272 281
273 return QualityMeasurementFactory.getBedMeasurements(river.getName(), from, to, startTime, endTime); 282 return QualityMeasurementFactory.getBedMeasurements(river.getName(), calcRange.getMinimumDouble(), calcRange.getMaximumDouble(), startTime, endTime);
274 } 283 }
275 284
276 /** 285 /**
277 * Checks the year difference between waterlevels and sounding, and issues a warning if too big. 286 * Checks the year difference between waterlevels and sounding, and issues a warning if too big.
278 * 287 *
294 303
295 final int maxDifference = getMaxDifferenceYears(soundingYear); 304 final int maxDifference = getMaxDifferenceYears(soundingYear);
296 305
297 final int difference = Math.abs(soundingYear - wstYear); 306 final int difference = Math.abs(soundingYear - wstYear);
298 if (difference > maxDifference) { 307 if (difference > maxDifference) {
299 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.year_difference", null, label, difference); 308 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.year_difference", null, label, wstYear,
309 soundingYear);
300 problems.addProblem(message); 310 problems.addProblem(message);
301 } 311 }
302 } 312 }
303 313
304 private int getMaxDifferenceYears(final int year) { 314 private int getMaxDifferenceYears(final int year) {
330 340
331 return null; 341 return null;
332 } 342 }
333 343
334 /* Checks if the discretisation of the waterlevel exceeds 1000m */ 344 /* Checks if the discretisation of the waterlevel exceeds 1000m */
335 // FIXME: vermutlich sollten wir diesen check auf den gültigkeitsbereich einschränken 345
336 private void checkWaterlevelDiscretisation(final WKms wstKms, final Calculation problems) { 346 private void checkWaterlevelDiscretisation(final WKms wstKms, final DoubleRange calcRange, final Calculation problems) {
347
337 final int size = wstKms.size(); 348 final int size = wstKms.size();
338 for (int i = 0; i < size - 2; i++) { 349 for (int i = 0; i < size - 2; i++) {
339 final double kmPrev = wstKms.getKm(i); 350 final double kmPrev = wstKms.getKm(i);
340 final double kmNext = wstKms.getKm(i + 1); 351 final double kmNext = wstKms.getKm(i + 1);
341 352
342 if (Math.abs(kmPrev - kmNext) > 1) { 353 /* only check if we are within the calculation range */
343 final String label = wstKms.getName(); 354 if (calcRange.overlapsRange(new DoubleRange(kmPrev, kmNext))) {
344 355 if (Math.abs(kmPrev - kmNext) > 1) {
345 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.waterlevel_discretisation", null, label); 356 final String label = wstKms.getName();
346 problems.addProblem(kmPrev, message); 357
358 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.waterlevel_discretisation", null, label);
359 problems.addProblem(kmPrev, message);
360 }
347 } 361 }
348 } 362 }
349 } 363 }
350 364
351 private BedHeight loadBedHeight(final String soundingId, final double from, final double to) { 365 private BedHeight loadBedHeight(final String soundingId) {
352 366
353 // REMARK: absolutely unbelievable.... 367 // REMARK: absolutely unbelievable....
354 // The way how bed-heights (and other data too) is accessed is different for nearly ever calculation-type 368 // The way how bed-heights (and other data too) is accessed is different for nearly ever calculation-type
355 // throughout flys. 369 // throughout flys.
356 // The knowledge on how to parse the datacage-ids is spread through the complete code-base... 370 // The knowledge on how to parse the datacage-ids is spread through the complete code-base...

http://dive4elements.wald.intevation.org