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

http://dive4elements.wald.intevation.org