# HG changeset patch # User mschaefer # Date 1519315446 -3600 # Node ID 0a900d605d523ffd11ae0aedf77cd8aedfcdf387 # Parent d32c22fc686ceb307d6641333346b92bd1819d01 S-INFO Flowdepth work on TKH calculation diff -r d32c22fc686c -r 0a900d605d52 artifacts/pom.xml --- a/artifacts/pom.xml Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/pom.xml Thu Feb 22 17:04:06 2018 +0100 @@ -42,7 +42,7 @@ - + diff -r d32c22fc686c -r 0a900d605d52 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/BedQualityD50KmValueFinder.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/BedQualityD50KmValueFinder.java Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/BedQualityD50KmValueFinder.java Thu Feb 22 17:04:06 2018 +0100 @@ -18,15 +18,22 @@ import org.apache.commons.math.analysis.interpolation.LinearInterpolator; import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; import org.apache.log4j.Logger; +import org.dive4elements.river.artifacts.math.Utils; import org.dive4elements.river.artifacts.model.DateRange; import org.dive4elements.river.backend.SedDBSessionHolder; import org.dive4elements.river.model.River; +import org.dive4elements.river.utils.DoubleUtil; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.type.StandardBasicTypes; +import gnu.trove.TDoubleArrayList; + /** - * Searchable sorted km array with parallel bed measurements value array and linear interpolation for km and d50 between the array elements. + * Searchable sorted km array with parallel bed measurements value array and linear interpolation for km and d50 between the array elements.
+ *
+ * See comment of SQL command on how the values are filtered and aggregated. + * * @author Matthias Schäfer * */ @@ -154,18 +161,35 @@ private static final String[] SQL_BED_D50_SELECT_ALIAS = {"km", "mindate", "maxdate", "cnt", "mindepth", "maxdepth", "d50"}; /** - * Real linear interpolator for kms and d50 values + * Kms of the loaded river range */ - private PolynomialSplineFunction interpolator; + private TDoubleArrayList kms; + + /** + * D50 for each km in kms + */ + private TDoubleArrayList values; + /***** METHODS *****/ /** * Returns the d50 value interpolated according to a km - * @throws ArgumentOutsideDomainException + * @return d50 (mm) of the km, or NaN */ public double findD50(double km) throws ArgumentOutsideDomainException { - return interpolator.value(km); + if ((kms == null) || (kms.size() == 0)) + return Double.NaN; + int i = kms.binarySearch(km); + if (i >= 0) + return values.get(i); + i = -i - 1; + if ((i - 1 >= 0) && Utils.epsilonEquals(km, kms.get(i - 1), 0.0001)) + return values.get(i - 1); + else if ((i >= 0) && (i <= kms.size() - 1) && Utils.epsilonEquals(km, kms.get(i), 0.0001)) + return values.get(i); + else + return Double.NaN; } /** @@ -191,18 +215,15 @@ sqlQuery.setDate("todate", dateRange.getTo()); @SuppressWarnings("unchecked") final List rows = sqlQuery.list(); - final double[] kms = new double[rows.size()]; - final double[] values = new double[rows.size()]; + kms = new TDoubleArrayList(); + values = new TDoubleArrayList(); D50Measurement measurement; - int i = -1; for (Object[] row : rows) { measurement = new D50Measurement(row, SQL_BED_D50_SELECT_ALIAS); - i++; - kms[i] = measurement.getKm(); - values[i] = measurement.getD50(); - log.debug(String.format("loadValues km %.3f d50(mm) %.1f count %d", kms[i], values[i], measurement.getCnt())); + kms.add(measurement.getKm()); + values.add(measurement.getD50()); + log.debug(String.format("loadValues km %.3f d50(mm) %.1f count %d", kms.get(kms.size()-1), values.get(values.size()-1), measurement.getCnt())); } - interpolator = new LinearInterpolator().interpolate(kms, values); return true; } diff -r d32c22fc686c -r 0a900d605d52 artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/FlowDepthCalculation.java Thu Feb 22 17:04:06 2018 +0100 @@ -27,7 +27,7 @@ import org.dive4elements.river.artifacts.model.CalculationResult; import org.dive4elements.river.artifacts.model.DateRange; import org.dive4elements.river.artifacts.model.LocationProvider; -import org.dive4elements.river.artifacts.model.WQKms; +import org.dive4elements.river.artifacts.model.QKms; import org.dive4elements.river.artifacts.model.WKms; import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.artifacts.sinfo.SINFOArtifact; @@ -111,7 +111,6 @@ final String wstId = diffPair.getWstId(); final BedHeight bedHeight = loadBedHeight(soundingId); - final BedHeight bedHeight = loadBedHeight(soundingId); if (bedHeight == null) { final String message = Resources.format(this.context.getMeta(), "Failed to access sounding with id '{0}'", soundingId); problems.addProblem(message); @@ -133,7 +132,7 @@ checkYearDifference(label, waterlevel, bedHeight, problems); checkWaterlevelDiscretisation(wstKms, calcRange, problems); - // TODO: prüfen, ob sohlhöen die calcRange abdecken/überschneiden + // TODO: prüfen, ob sohlhöhen die calcRange abdecken/überschneiden /* re-determine the reference gauge, in the same way as the WaterlevelArtifact would do it */ final String notinrange = Resources.getMsg(this.context.getMeta(), CSV_NOT_IN_GAUGE_RANGE, CSV_NOT_IN_GAUGE_RANGE); @@ -147,19 +146,16 @@ final FlowDepthCalculationResult resultData = new FlowDepthCalculationResult(label, wstInfo, sounding); - // FIXME: nur prüfen/beschaffen wenn TKH Berechnung aktiv - /* Abflusswerte vorhanden? */ - if (!(wstKms instanceof WQKms)) { + boolean doCalcTkh = useTkh; + if (doCalcTkh && !(wstKms instanceof QKms)) { final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingQ", null, label); problems.addProblem(message); - // TODO: keine Berechnung TKH + doCalcTkh = false; } BedQualityD50KmValueFinder bedMeasurementsFinder = null; - if (useTkh) - bedMeasurementsFinder = loadBedMeasurements(river, calcRange, sounding.getYear()); - // FIXME: prüfung ob (genug) werte vorhanden sind? was sind genau die kriterien? falls nein, problem hinzufügen und keine - // berechnung tkh + if (doCalcTkh) + bedMeasurementsFinder = loadBedMeasurements(river, calcRange, sounding.getYear().intValue()); final String bedHeightLabel = bedHeight.getDescription(); final String wstLabel = wstKms.getName(); @@ -167,9 +163,9 @@ final UnivariateRealFunction wstInterpolator = DoubleUtil.getLinearInterpolator(wstKms.allKms(), wstKms.allWs()); UnivariateRealFunction qInterpolator = null; DoubleRange qRange = null; - if (useTkh && (wstKms instanceof WQKms)) { - qInterpolator = DoubleUtil.getLinearInterpolator(((WQKms) wstKms).allKms(), ((WQKms) wstKms).allQs()); - qRange = new DoubleRange( ((WQKms) wstKms).allQs().min(), ((WQKms) wstKms).allQs().max()); + if (doCalcTkh) { + qInterpolator = DoubleUtil.getLinearInterpolator(((QKms) wstKms).allKms(), ((QKms) wstKms).allQs()); + qRange = new DoubleRange( ((QKms) wstKms).allQs().min(), ((QKms) wstKms).allQs().max()); } // FIXME: sort by station first, but in what direction? @@ -182,13 +178,13 @@ // FIXME: wie wird ggf. interpoliert? prüfung ob werte vorhanden? /* SoilKind lastKind = SoilKind.mobil; */ SoilKindKmValueFinder soilKindFinder = null; - if (useTkh) { + if (doCalcTkh) { soilKindFinder = new SoilKindKmValueFinder(); soilKindFinder.loadValues(river, calcRange); } FlowVelocityModelKmValueFinder flowVelocitiesFinder = null; - if (useTkh) { + if (doCalcTkh) { flowVelocitiesFinder = new FlowVelocityModelKmValueFinder(); flowVelocitiesFinder.loadValues(river, calcRange, qRange); } @@ -208,8 +204,6 @@ if (!calcRange.containsDouble(km)) continue; - if (!calcRange.containsDouble(km)) - continue; try { // FIXME: check out of range @@ -227,33 +221,38 @@ // FIXME: calculate tkh double tkh = 0; - if (useTkh) { - double d50 = 0; - try { - d50 = bedMeasurementsFinder.findD50(km); - } catch (Exception e) { + if (doCalcTkh) { + double d50 = bedMeasurementsFinder.findD50(km); + if (Double.isNaN(d50)) { final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingD50", null, label); problems.addProblem(km, message); - //FIXME: cumulate problems + //FIXME: cumulate problems to one message? } - if (flowVelocitiesFinder.findKmQValues(km, discharge)) { - tkh = calculateTkh(wst - meanBedHeight, flowVelocitiesFinder.getFindVmainFound(), d50, flowVelocitiesFinder.getFindTauFound()); - log.debug(String.format("calculateTkh km %.3f q %.0f w %.2f mbh %.2f vm %.1f tau %.1f d50(mm) %.1f tkh(cm) %.1f", - km, discharge, wst, meanBedHeight, flowVelocitiesFinder.getFindVmainFound(), flowVelocitiesFinder.getFindTauFound(), d50*1000, tkh)); + if (!Double.isNaN(d50)) { + if (flowVelocitiesFinder.findKmQValues(km, discharge)) { + tkh = calculateTkh(wst - meanBedHeight, flowVelocitiesFinder.getFindVmainFound(), d50, flowVelocitiesFinder.getFindTauFound()); + /* log.debug(String.format("calculateTkh km %.3f q %.0f w %.2f mbh %.2f vm %.1f tau %.1f d50(mm) %.1f tkh(cm) %.1f", + km, discharge, wst, meanBedHeight, flowVelocitiesFinder.getFindVmainFound(), flowVelocitiesFinder.getFindTauFound(), d50*1000, tkh)); */ + } + else { + final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingQ", null, label); + problems.addProblem(km, message); + //FIXME: cumulate problems to one message? + } } else tkh = Double.NaN; } // Soil kind - SoilKind kind = SoilKind.starr; - if (useTkh) { + SoilKind kind = SoilKind.mobil; + if (doCalcTkh) { try { kind = soilKindFinder.findSoilKind(km); } catch (Exception e) { final String message = Resources.getMsg(this.context.getMeta(), "sinfo_calc_flow_depth.warning.missingSoilKind", null, label); problems.addProblem(km, message); - //FIXME: cumulate problems + //FIXME: cumulate problems to one message? } } diff -r d32c22fc686c -r 0a900d605d52 artifacts/src/main/resources/messages.properties --- a/artifacts/src/main/resources/messages.properties Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/src/main/resources/messages.properties Thu Feb 22 17:04:06 2018 +0100 @@ -773,8 +773,8 @@ sinfo_calc_flow_depth.warning.missingQ = {0}: keine Abflussdaten vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth.warning.waterlevel_discretisation = Wasserspiegel {0}: r\u00e4umliche Aufl\u00f6sung betr\u00e4gt mehr als 1000m sinfo_calc_flow_depth.warning.year_difference = {0}: Sie verwenden als Differenzenpaar eine Wasserspiegellage aus dem Jahr {1} und eine Peilung aus dem Jahr {2}. Dies kann zu unplausiblen Werten f\u00fchren. -sinfo_calc_flow_depth.warning.missingSoilKind = {0}: no soil kind available -sinfo_calc_flow_depth.warning.missingD50 = {0}: no d50 available +sinfo_calc_flow_depth.warning.missingSoilKind = {0}: keine Sohlart vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich +sinfo_calc_flow_depth.warning.missingD50 = {0}: kein D50 vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe diff -r d32c22fc686c -r 0a900d605d52 artifacts/src/main/resources/messages_de.properties --- a/artifacts/src/main/resources/messages_de.properties Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/src/main/resources/messages_de.properties Thu Feb 22 17:04:06 2018 +0100 @@ -779,8 +779,8 @@ sinfo_calc_flow_depth.warning.missingQ = {0}: keine Abflussdaten vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth.warning.waterlevel_discretisation = Wasserspiegel {0}: r\u00e4umliche Aufl\u00f6sung betr\u00e4gt mehr als 1000m sinfo_calc_flow_depth.warning.year_difference = {0}: Sie verwenden als Differenzenpaar eine Wasserspiegellage aus dem Jahr {1} und eine Peilung aus dem Jahr {2}. Dies kann zu unplausiblen Werten f\u00fchren. -sinfo_calc_flow_depth.warning.missingSoilKind = {0}: keine Sohlart vorhanden -sinfo_calc_flow_depth.warning.missingD50 = {0}: kein D50 vorhanden +sinfo_calc_flow_depth.warning.missingSoilKind = {0}: keine Sohlart vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich +sinfo_calc_flow_depth.warning.missingD50 = {0}: kein D50 vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe diff -r d32c22fc686c -r 0a900d605d52 artifacts/src/main/resources/messages_de_DE.properties --- a/artifacts/src/main/resources/messages_de_DE.properties Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/src/main/resources/messages_de_DE.properties Thu Feb 22 17:04:06 2018 +0100 @@ -775,6 +775,8 @@ sinfo_calc_flow_depth.warning.missingQ = {0}: keine Abflussdaten vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth.warning.waterlevel_discretisation = Wasserspiegel {0}: r\u00e4umliche Aufl\u00f6sung betr\u00e4gt mehr als 1000m sinfo_calc_flow_depth.warning.year_difference = {0}: Sie verwenden als Differenzenpaar eine Wasserspiegellage aus dem Jahr {1} und eine Peilung aus dem Jahr {2}. Dies kann zu unplausiblen Werten f\u00fchren. +sinfo_calc_flow_depth.warning.missingSoilKind = {0}: keine Sohlart vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich +sinfo_calc_flow_depth.warning.missingD50 = {0}: kein D50 vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich Zeitliche Abweichung betr\u00e4gt {1} Jahre. Dies kann zu unplausiblen Ergebnissen f\u00fchren diff -r d32c22fc686c -r 0a900d605d52 artifacts/src/main/resources/messages_en.properties --- a/artifacts/src/main/resources/messages_en.properties Thu Feb 22 14:11:19 2018 +0100 +++ b/artifacts/src/main/resources/messages_en.properties Thu Feb 22 17:04:06 2018 +0100 @@ -774,6 +774,8 @@ sinfo_calc_flow_depth.warning.missingQ = {0}: keine Abflussdaten vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth.warning.waterlevel_discretisation = Wasserspiegel {0}: r\u00e4umliche Aufl\u00f6sung betr\u00e4gt mehr als 1000m sinfo_calc_flow_depth.warning.year_difference = {0}: Sie verwenden als Differenzenpaar eine Wasserspiegellage aus dem Jahr {1} und eine Peilung aus dem Jahr {2}. Dies kann zu unplausiblen Werten f\u00fchren. +sinfo_calc_flow_depth.warning.missingSoilKind = {0}: keine Sohlart vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich +sinfo_calc_flow_depth.warning.missingD50 = {0}: kein D50 vorhanden, Transportk\u00f6rperh\u00f6henberechnung nicht m\u00f6glich sinfo_calc_flow_depth_development=Flie\u00dftiefenentwicklung sinfo_calc_flow_depth_minmax=Minimale und Maximale Flie\u00dftiefe