Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/tkhcalculation/BedQualityD50KmValueFinder.java @ 9522:23d97d60b889
Selection range of D50 values for tkh calculation can now be configured with a river specific table.
author | gernotbelger |
---|---|
date | Mon, 01 Oct 2018 16:37:12 +0200 |
parents | c01f1e65903b |
children | 8e6b9cb9486a |
comparison
equal
deleted
inserted
replaced
9521:ce54388d6efe | 9522:23d97d60b889 |
---|---|
8 * documentation coming with Dive4Elements River for details. | 8 * documentation coming with Dive4Elements River for details. |
9 */ | 9 */ |
10 | 10 |
11 package org.dive4elements.river.artifacts.sinfo.tkhcalculation; | 11 package org.dive4elements.river.artifacts.sinfo.tkhcalculation; |
12 | 12 |
13 import java.util.Calendar; | 13 import java.io.IOException; |
14 import java.util.Date; | 14 import java.util.Date; |
15 import java.util.List; | 15 import java.util.List; |
16 | 16 |
17 import org.apache.commons.lang.math.DoubleRange; | 17 import org.apache.commons.lang.math.DoubleRange; |
18 import org.apache.commons.math.ArgumentOutsideDomainException; | 18 import org.apache.commons.math.ArgumentOutsideDomainException; |
19 import org.apache.commons.math.analysis.interpolation.LinearInterpolator; | 19 import org.apache.commons.math.analysis.interpolation.LinearInterpolator; |
20 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; | 20 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; |
21 import org.apache.log4j.Logger; | 21 import org.apache.log4j.Logger; |
22 import org.dive4elements.river.artifacts.math.Utils; | 22 import org.dive4elements.river.artifacts.math.Utils; |
23 import org.dive4elements.river.artifacts.model.Calculation; | 23 import org.dive4elements.river.artifacts.model.Calculation; |
24 import org.dive4elements.river.artifacts.model.DateRange; | |
25 import org.dive4elements.river.artifacts.sinfo.tkhstate.BedQualityD50TimeRangeConfig; | |
26 import org.dive4elements.river.artifacts.sinfo.tkhstate.BedQualityD50TimeRangeConfig.BedQualityParseException; | |
27 import org.dive4elements.river.artifacts.sinfo.tkhstate.TsvHelper.TsvReaderException; | |
24 import org.dive4elements.river.backend.SedDBSessionHolder; | 28 import org.dive4elements.river.backend.SedDBSessionHolder; |
25 import org.dive4elements.river.model.River; | 29 import org.dive4elements.river.model.River; |
26 import org.hibernate.SQLQuery; | 30 import org.hibernate.SQLQuery; |
27 import org.hibernate.Session; | 31 import org.hibernate.Session; |
28 import org.hibernate.type.StandardBasicTypes; | 32 import org.hibernate.type.StandardBasicTypes; |
55 * | 59 * |
56 * If PostgreSQL would support a median aggregate function like Oracle does, the aggregation could be placed into this | 60 * If PostgreSQL would support a median aggregate function like Oracle does, the aggregation could be placed into this |
57 * query. | 61 * query. |
58 */ | 62 */ |
59 private static final String SQL_BED_D50_SUBLAYER_MEASUREMENT = // | 63 private static final String SQL_BED_D50_SUBLAYER_MEASUREMENT = // |
60 "SELECT s.km, t.datum, p.tiefevon, p.tiefebis, a.d50" | 64 "SELECT s.km, t.datum, p.tiefevon, p.tiefebis, a.d50" // |
61 + " FROM sohltest t INNER JOIN station s ON t.stationid = s.stationid" | 65 + " FROM sohltest t INNER JOIN station s ON t.stationid = s.stationid" // |
62 + " INNER JOIN gewaesser g ON s.gewaesserid = g.gewaesserid" | 66 + " INNER JOIN gewaesser g ON s.gewaesserid = g.gewaesserid" // |
63 + " INNER JOIN sohlprobe p ON t.sohltestid = p.sohltestid" | 67 + " INNER JOIN sohlprobe p ON t.sohltestid = p.sohltestid" // |
64 + " INNER JOIN siebanalyse a ON p.sohlprobeid = a.sohlprobeid" | 68 + " INNER JOIN siebanalyse a ON p.sohlprobeid = a.sohlprobeid" // |
65 + " WHERE (g.name = :name)" | 69 + " WHERE (g.name = :name)" // |
66 + " AND (p.tiefevon > 0.0) AND (p.tiefebis <= 0.5)" | 70 + " AND (p.tiefevon > 0.0) AND (p.tiefebis <= 0.5)" // |
67 + " AND (t.datum BETWEEN :fromdate AND :todate)" | 71 + " AND (t.datum BETWEEN :fromdate AND :todate)" // |
68 + " ORDER BY s.km ASC, a.d50 ASC"; | 72 + " ORDER BY s.km ASC, a.d50 ASC"; |
69 | 73 |
70 // + " WHERE (g.name = :name) AND (s.km BETWEEN :fromkm - 0.0001 AND :tokm + 0.0001)" | 74 public static final Date MIN_DATE = new Date(-10000000000000l); // Database does not cope with Long.MIN/Long.Max, so we go just a few hundred years |
71 // + " AND (p.tiefevon > 0.0) AND (p.tiefebis <= 0.5)" | 75 // back/forward |
72 // + " AND (t.datum BETWEEN :fromdate AND :todate)" | 76 public static final Date MAX_DATE = new Date(10000000000000l); |
73 // + " ORDER BY s.km ASC, a.d50 ASC"; | |
74 | 77 |
75 private Calculation problems; | 78 private Calculation problems; |
76 | 79 |
77 /** | 80 /** |
78 * Real linear interpolator for kms and d50 values (m) | 81 * Real linear interpolator for kms and d50 values (m) |
92 /** | 95 /** |
93 * Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb) | 96 * Sohlbeschaffenheit (D50 Korndurchmesser aus Seddb) |
94 * Abhängig von Peiljahr | 97 * Abhängig von Peiljahr |
95 * | 98 * |
96 * @param problems | 99 * @param problems |
100 * @throws BedQualityParseException | |
101 * @throws TsvReaderException | |
102 * @throws IOException | |
97 */ | 103 */ |
98 public static BedQualityD50KmValueFinder loadBedMeasurements(final Calculation problems, final River river, final DoubleRange kmRange, | 104 public static BedQualityD50KmValueFinder loadBedMeasurements(final Calculation problems, final River river, final DoubleRange kmRange, |
99 final int soundingYear, final int validYears) { | 105 final int soundingYear) throws BedQualityParseException, IOException, TsvReaderException { |
100 | 106 |
101 /* construct valid measurement time range */ | 107 final DateRange rangeFromConfigFile = BedQualityD50TimeRangeConfig.getDefaults(river, soundingYear, problems); |
102 final Calendar cal = Calendar.getInstance(); | 108 final DateRange dateRange = rangeFromConfigFile != null ? rangeFromConfigFile : new DateRange(MIN_DATE, MAX_DATE); |
103 cal.clear(); | 109 return loadBedMeasurements(problems, river, kmRange, dateRange, soundingYear); |
110 } | |
104 | 111 |
105 cal.set(soundingYear - validYears, 0, 1); | 112 private static BedQualityD50KmValueFinder loadBedMeasurements(final Calculation problems, final River river, final DoubleRange kmRange, |
106 final Date startTime = cal.getTime(); | 113 final DateRange dateRange, final int soundingYear) { |
107 | 114 |
108 cal.set(soundingYear + validYears, 11, 31); | 115 final Date startTime = dateRange.getFrom(); |
109 final Date endTime = cal.getTime(); | 116 final Date endTime = dateRange.getTo(); |
110 | 117 |
111 final String seddbRiver = river.nameForSeddb(); | 118 final String seddbRiver = river.nameForSeddb(); |
112 log.debug(String.format("loadValues '%s' km %.3f - %.3f %tF - %tF", seddbRiver, kmRange.getMinimumDouble(), kmRange.getMaximumDouble(), startTime, | 119 log.debug(String.format("loadValues '%s' km %.3f - %.3f %tF - %tF", seddbRiver, kmRange.getMinimumDouble(), kmRange.getMaximumDouble(), startTime, |
113 endTime)); | 120 endTime)); |
114 final Session session = SedDBSessionHolder.HOLDER.get(); | 121 final Session session = SedDBSessionHolder.HOLDER.get(); |
169 */ | 176 */ |
170 public double findD50(final double km) { | 177 public double findD50(final double km) { |
171 try { | 178 try { |
172 return this.interpolator.value(km); | 179 return this.interpolator.value(km); |
173 } | 180 } |
174 catch (final ArgumentOutsideDomainException e) { | 181 catch (@SuppressWarnings("unused") final ArgumentOutsideDomainException e) { |
175 // No stack trace because this might happen a lot (intended) and we produce an error message anyways. | 182 // No stack trace because this might happen a lot (intended) and we produce an error message anyways. |
176 // e.printStackTrace(); | 183 // e.printStackTrace(); |
177 | 184 |
178 if (this.problems != null) { | 185 if (this.problems != null) { |
179 this.problems.addProblem(km, "bedqualityd50kmvaluefinder.missing"); | 186 this.problems.addProblem(km, "bedqualityd50kmvaluefinder.missing"); |
180 // Report only once | 187 // Report only once |