Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java @ 8882:f762fadc5313
Further work on SINFO-FlowDepth
author | gernotbelger |
---|---|
date | Fri, 09 Feb 2018 16:11:47 +0100 |
parents | 64ca63f79f6f |
children | a536e1aacf0f |
comparison
equal
deleted
inserted
replaced
8881:6b93a2498e06 | 8882:f762fadc5313 |
---|---|
21 import org.dive4elements.river.artifacts.model.QKms; | 21 import org.dive4elements.river.artifacts.model.QKms; |
22 import org.dive4elements.river.artifacts.model.WKms; | 22 import org.dive4elements.river.artifacts.model.WKms; |
23 import org.dive4elements.river.artifacts.resources.Resources; | 23 import org.dive4elements.river.artifacts.resources.Resources; |
24 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; | 24 import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; |
25 import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthAccess.DifferencesPair; | 25 import org.dive4elements.river.artifacts.sinfo.flowdepth.FlowDepthAccess.DifferencesPair; |
26 import org.dive4elements.river.artifacts.states.WDifferencesState; | 26 import org.dive4elements.river.artifacts.states.WaterlevelData; |
27 import org.dive4elements.river.artifacts.states.WaterlevelFetcher; | |
27 import org.dive4elements.river.model.BedHeight; | 28 import org.dive4elements.river.model.BedHeight; |
28 import org.dive4elements.river.model.Gauge; | 29 import org.dive4elements.river.model.Gauge; |
29 import org.dive4elements.river.model.River; | 30 import org.dive4elements.river.model.River; |
30 import org.dive4elements.river.utils.GaugeIndex; | 31 import org.dive4elements.river.utils.GaugeIndex; |
31 import org.dive4elements.river.utils.RiverUtils; | 32 import org.dive4elements.river.utils.RiverUtils; |
34 | 35 |
35 private static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range"; | 36 private static final String CSV_NOT_IN_GAUGE_RANGE = "export.waterlevel.csv.not.in.gauge.range"; |
36 | 37 |
37 private final CallContext context; | 38 private final CallContext context; |
38 | 39 |
39 public FlowDepthCalculation( final CallContext context ) { | 40 public FlowDepthCalculation(final CallContext context) { |
40 this.context = context; | 41 this.context = context; |
41 } | 42 } |
42 | 43 |
43 public CalculationResult calculate(final SINFOArtifact sinfo) { | 44 public CalculationResult calculate(final SINFOArtifact sinfo) { |
44 | 45 |
64 final Calculation problems = new Calculation(); | 65 final Calculation problems = new Calculation(); |
65 | 66 |
66 final List<Gauge> gauges = river.determineGauges(from, to); | 67 final List<Gauge> gauges = river.determineGauges(from, to); |
67 final GaugeIndex gaugeIndex = new GaugeIndex(gauges); | 68 final GaugeIndex gaugeIndex = new GaugeIndex(gauges); |
68 | 69 |
69 final String calcModeLabel = Resources.getMsg(this.context.getMeta(),sinfo.getCalculationMode().name() ); | 70 final String calcModeLabel = Resources.getMsg(this.context.getMeta(), sinfo.getCalculationMode().name()); |
70 | 71 |
71 final FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, river, from, to, useTkh); | 72 final FlowDepthCalculationResults results = new FlowDepthCalculationResults(calcModeLabel, user, river, from, |
73 to, useTkh); | |
72 | 74 |
73 for (final DifferencesPair diffPair : diffPairs) { | 75 for (final DifferencesPair diffPair : diffPairs) { |
74 final FlowDepthCalculationResult result = calculateResult( river, from, to, diffPair, problems, gaugeIndex ); | 76 final FlowDepthCalculationResult result = calculateResult(river, from, to, diffPair, problems, gaugeIndex); |
75 if( result != null ) | 77 if (result != null) |
76 results.addResult(result); | 78 results.addResult(result); |
77 } | 79 } |
78 | 80 |
79 return new CalculationResult(results,problems); | 81 return new CalculationResult(results, problems); |
80 } | 82 } |
81 | 83 |
82 private FlowDepthCalculationResult calculateResult(final River river, final double from, final double to, final DifferencesPair diffPair, final Calculation problems, final GaugeIndex gaugeIndex) { | 84 private FlowDepthCalculationResult calculateResult(final River river, final double from, final double to, |
85 final DifferencesPair diffPair, final Calculation problems, final GaugeIndex gaugeIndex) { | |
83 | 86 |
84 /* access real input data from database */ | 87 /* access real input data from database */ |
85 final String soundingId = diffPair.getSoundingId(); | 88 final String soundingId = diffPair.getSoundingId(); |
86 final String wstId = diffPair.getWstId(); | 89 final String wstId = diffPair.getWstId(); |
87 | 90 |
88 final BedHeight bedHeight = loadBedHeight( soundingId, from, to ); | 91 final BedHeight bedHeight = loadBedHeight(soundingId, from, to); |
89 if( bedHeight == null ) | 92 if (bedHeight == null) { |
90 { | 93 final String message = Resources.format(this.context.getMeta(), "Failed to access sounding with id '{0}'", |
91 final String message = Resources.format(this.context.getMeta(), "Failed to access sounding with id '{0}'", soundingId); | 94 soundingId); |
92 problems.addProblem(message); | 95 problems.addProblem(message); |
93 return null; | 96 return null; |
94 } | 97 } |
95 | 98 |
96 final WKms wstKms = new WDifferencesState().getWKms(wstId, this.context, from, to); | 99 /* REMARK: fetch ALL wst kms, because we want to determine the original reference gauge */ |
97 if( wstKms == null ) | 100 final WaterlevelData waterlevel = new WaterlevelFetcher().findWaterlevel(this.context, wstId, Double.NaN, |
98 { | 101 Double.NaN); |
99 final String message = Resources.format(this.context.getMeta(), "Failed to access waterlevel with id '{0}'", wstId); | 102 if (waterlevel == null) { |
103 final String message = Resources.format(this.context.getMeta(), "Failed to access waterlevel with id '{0}'", | |
104 wstId); | |
100 problems.addProblem(message); | 105 problems.addProblem(message); |
101 return null; | 106 return null; |
102 } | 107 } |
108 final WKms wstKms = waterlevel.getWkms(); | |
109 | |
110 checkWaterlevelDiscretisation(wstKms, problems); | |
103 | 111 |
104 // FIXME: woher bekommen? | 112 // FIXME: woher bekommen? |
105 final int wspYear = 0; | 113 final int wspYear = 0; |
106 // FIXME: angeblich metadatum bestimmter wsps? | 114 |
107 // Könnte 'source' an 'wst_columns' sein | 115 /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */ |
108 final String wspSource = "FIXME"; | 116 final String notinrange = Resources.getMsg(this.context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, |
109 // FIXME: Umsetzung IDENTISCH zu allen möglichen Arten wie ein WSPL berechnet wird.... | 117 CSV_NOT_IN_GAUGE_RANGE); |
110 final String wspGauge = "FIXME"; | 118 |
119 final Gauge refGauge = waterlevel.findReferenceGauge(river); | |
120 final String refGaugeName = refGauge == null ? notinrange : refGauge.getName(); | |
111 | 121 |
112 final String wspLabel = wstKms.getName(); | 122 final String wspLabel = wstKms.getName(); |
113 final String soundingLabel = bedHeight.getDescription(); | 123 final String soundingLabel = bedHeight.getDescription(); |
114 final String label = String.format("%s - %s", wspLabel, soundingLabel); | 124 final String label = String.format("%s - %s", wspLabel, soundingLabel); |
115 | 125 |
116 final BedHeightInfo sounding = BedHeightInfo.from(bedHeight); | 126 final BedHeightInfo sounding = BedHeightInfo.from(bedHeight); |
117 final WstInfo wstInfo = new WstInfo(wspLabel, wspYear, wspSource, wspGauge); | 127 final WstInfo wstInfo = new WstInfo(wspLabel, wspYear, refGaugeName); |
118 | 128 |
119 final FlowDepthCalculationResult resultData = new FlowDepthCalculationResult(label, wstInfo, sounding); | 129 final FlowDepthCalculationResult resultData = new FlowDepthCalculationResult(label, wstInfo, sounding); |
120 | 130 |
121 final String notinrange = Resources.getMsg(this.context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE); | |
122 | |
123 // TODO: prüfe diskretisierung wsp --> > 1000m --> Fehlermeldung | |
124 | |
125 // TODO: Berechnung der Transportkörperhöhen | 131 // TODO: Berechnung der Transportkörperhöhen |
126 // - woher kommen die zusätzlichen eingangsdaten? sind das fixe daten pro gewässer? --> falls ja, warum nicht einmal berechnen und in db ablegen? | 132 // - woher kommen die zusätzlichen eingangsdaten? sind das fixe daten pro gewässer? --> falls ja, warum nicht |
133 // einmal berechnen und in db ablegen? | |
127 | 134 |
128 // Benötigte Daten | 135 // Benötigte Daten |
129 // - Abfluss / Station | 136 // - Abfluss / Station |
130 // - kein Abfluss --> Fehler | 137 // - kein Abfluss --> Fehler |
131 if( !(wstKms instanceof QKms)) | 138 if (!(wstKms instanceof QKms)) { |
132 { | 139 final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingQ", |
133 final String message = Resources.format(this.context.getMeta(), "{0}: keine Abflussdaten vorhanden, Transportkörperhöhenberechnung nicht möglich", label); | 140 null, label); |
134 problems.addProblem(message); | 141 problems.addProblem(message); |
135 // TODO: keine Berechnung TKH | 142 // TODO: keine Berechnung TKH |
136 } | 143 } |
137 | 144 |
138 // - Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb) | 145 // - Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb) |
139 // - Abhängig von Peiljahr | 146 // - Abhängig von Peiljahr |
140 // - kein D50 vorhanden --> Fehler | 147 // - kein D50 vorhanden --> Fehler |
141 // - Art der Gewässersohle (starr/mobil) | 148 // - Art der Gewässersohle (starr/mobil) |
142 | |
143 | 149 |
144 final String bedHeightLabel = bedHeight.getDescription(); | 150 final String bedHeightLabel = bedHeight.getDescription(); |
145 final String wstLabel = wstKms.getName(); | 151 final String wstLabel = wstKms.getName(); |
146 | 152 |
147 // FIXME: basis der diskretisierung ist bedHeight, die wspl werden interpoliert | 153 // FIXME: basis der diskretisierung ist bedHeight, die wspl werden interpoliert |
162 | 168 |
163 // REMARK: access the location once only during calculation | 169 // REMARK: access the location once only during calculation |
164 final String location = LocationProvider.getLocation(river.getName(), km); | 170 final String location = LocationProvider.getLocation(river.getName(), km); |
165 | 171 |
166 // REMARK: access the gauge once only during calculation | 172 // REMARK: access the gauge once only during calculation |
167 // FIXME: copy specific handling from original wst | 173 final Gauge gauge = findGauge(waterlevel, refGauge, gaugeIndex, km); |
168 final Gauge gauge = gaugeIndex.findGauge(km); | 174 |
169 final String gaugeLabel = gauge == null ? notinrange : gauge.getName(); | 175 final String gaugeLabel = gauge == null ? notinrange : gauge.getName(); |
170 | 176 |
171 resultData.addRow( km, flowDepth, flowDepthTkh, tkh, wst, discharge, wstLabel, gaugeLabel, meanBedHeight, bedHeightLabel, location ); | 177 resultData.addRow(km, flowDepth, flowDepthTkh, tkh, wst, discharge, wstLabel, gaugeLabel, meanBedHeight, |
178 bedHeightLabel, location); | |
172 } | 179 } |
173 | 180 |
174 return resultData; | 181 return resultData; |
175 } | 182 } |
176 | 183 |
184 private Gauge findGauge(final WaterlevelData waterlevel, final Gauge refGauge, final GaugeIndex gaugeIndex, | |
185 final double km) { | |
186 | |
187 // REMARK: using same logic as in WaterlevelExporter here | |
188 | |
189 final boolean showAllGauges = waterlevel.isShowAllGauges(); | |
190 | |
191 if (showAllGauges) | |
192 return gaugeIndex.findGauge(km); | |
193 | |
194 if (refGauge.getRange().contains(km)) | |
195 return refGauge; | |
196 | |
197 return null; | |
198 } | |
199 | |
200 /* Checks if the discretisation of the waterlevel exceeds 1000m */ | |
201 private void checkWaterlevelDiscretisation(final WKms wstKms, final Calculation problems) { | |
202 final int size = wstKms.size(); | |
203 for (int i = 0; i < size - 2; i++) { | |
204 final double kmPrev = wstKms.getKm(i); | |
205 final double kmNext = wstKms.getKm(i + 1); | |
206 | |
207 if (Math.abs(kmPrev - kmNext) > 1) { | |
208 final String label = wstKms.getName(); | |
209 | |
210 final String message = Resources.getMsg(this.context.getMeta(), | |
211 "sinfo_calc_flow_depth.warning.waterlevel_discretisation", null, label); | |
212 problems.addProblem(kmPrev, message); | |
213 } | |
214 } | |
215 } | |
216 | |
177 private BedHeight loadBedHeight(final String soundingId, final double from, final double to) { | 217 private BedHeight loadBedHeight(final String soundingId, final double from, final double to) { |
178 | 218 |
179 // FIXME: absolutely unbelievable.... | 219 // FIXME: absolutely unbelievable.... |
180 // The way how bed-heights (and other data too) is accessed is different for nearly ever calculation-type throughout flys. | 220 // The way how bed-heights (and other data too) is accessed is different for nearly ever calculation-type |
221 // throughout flys. | |
181 // The knowledge on how to parse the datacage-ids is spread through the complete code-base... | 222 // The knowledge on how to parse the datacage-ids is spread through the complete code-base... |
182 | 223 |
183 // We use here the way on how bed-heights are accessed by the BedDifferenceAccess/BedDifferenceCalculation, but this is plain random | 224 // We use here the way on how bed-heights are accessed by the BedDifferenceAccess/BedDifferenceCalculation, but |
225 // this is plain random | |
184 final String[] parts = soundingId.split(";"); | 226 final String[] parts = soundingId.split(";"); |
185 | 227 |
186 final BedHeightsArtifact artifact = (BedHeightsArtifact) RiverUtils.getArtifact(parts[0], this.context); | 228 final BedHeightsArtifact artifact = (BedHeightsArtifact) RiverUtils.getArtifact(parts[0], this.context); |
187 | 229 |
188 final Integer bedheightId = artifact.getDataAsInteger("height_id"); | 230 final Integer bedheightId = artifact.getDataAsInteger("height_id"); |
189 // FIXME: this only works with type 'single'; unclear on how to distinguish from epoch data (or whatever the other type means) | 231 // FIXME: this only works with type 'single'; unclear on how to distinguish from epoch data (or whatever the |
232 // other type means) | |
190 // Luckily, the requirement is to only access 'single' data here. | 233 // Luckily, the requirement is to only access 'single' data here. |
191 // final String bedheightType = artifact.getDataAsString("type"); | 234 // final String bedheightType = artifact.getDataAsString("type"); |
192 | 235 |
193 // FIXME: BedDifferences uses this, but we also need the metadata of the BedHeight | 236 // FIXME: BedDifferences uses this, but we also need the metadata of the BedHeight |
194 // FIXME: second absolutely awful thing: BedHeight is a hibernate binding class, accessing the database via hibernate stuff | 237 // FIXME: second absolutely awful thing: BedHeight is a hibernate binding class, accessing the database via |
238 // hibernate stuff | |
195 // BedHeightFactory uses its own (direct) way of accessing the data, with its own implemented data classes. | 239 // BedHeightFactory uses its own (direct) way of accessing the data, with its own implemented data classes. |
196 //return BedHeightFactory.getHeight(bedheightType, bedheightId, from, to); | 240 // return BedHeightFactory.getHeight(bedheightType, bedheightId, from, to); |
197 | 241 |
198 return BedHeight.getBedHeightById(bedheightId); | 242 return BedHeight.getBedHeightById(bedheightId); |
199 } | 243 } |
200 } | 244 } |