comparison artifacts/src/main/java/org/dive4elements/river/artifacts/sinfo/flowdepth/BedQualityD50KmValueFinder.java @ 8901:0a900d605d52

S-INFO Flowdepth work on TKH calculation
author mschaefer
date Thu, 22 Feb 2018 17:04:06 +0100
parents 89f3c5462a16
children 37ff7f435912
comparison
equal deleted inserted replaced
8900:d32c22fc686c 8901:0a900d605d52
16 import org.apache.commons.lang.math.DoubleRange; 16 import org.apache.commons.lang.math.DoubleRange;
17 import org.apache.commons.math.ArgumentOutsideDomainException; 17 import org.apache.commons.math.ArgumentOutsideDomainException;
18 import org.apache.commons.math.analysis.interpolation.LinearInterpolator; 18 import org.apache.commons.math.analysis.interpolation.LinearInterpolator;
19 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction; 19 import org.apache.commons.math.analysis.polynomials.PolynomialSplineFunction;
20 import org.apache.log4j.Logger; 20 import org.apache.log4j.Logger;
21 import org.dive4elements.river.artifacts.math.Utils;
21 import org.dive4elements.river.artifacts.model.DateRange; 22 import org.dive4elements.river.artifacts.model.DateRange;
22 import org.dive4elements.river.backend.SedDBSessionHolder; 23 import org.dive4elements.river.backend.SedDBSessionHolder;
23 import org.dive4elements.river.model.River; 24 import org.dive4elements.river.model.River;
25 import org.dive4elements.river.utils.DoubleUtil;
24 import org.hibernate.SQLQuery; 26 import org.hibernate.SQLQuery;
25 import org.hibernate.Session; 27 import org.hibernate.Session;
26 import org.hibernate.type.StandardBasicTypes; 28 import org.hibernate.type.StandardBasicTypes;
27 29
30 import gnu.trove.TDoubleArrayList;
31
28 /** 32 /**
29 * Searchable sorted km array with parallel bed measurements value array and linear interpolation for km and d50 between the array elements. 33 * Searchable sorted km array with parallel bed measurements value array and linear interpolation for km and d50 between the array elements.<br />
34 * <br />
35 * See comment of SQL command on how the values are filtered and aggregated.
36 *
30 * @author Matthias Schäfer 37 * @author Matthias Schäfer
31 * 38 *
32 */ 39 */
33 public class BedQualityD50KmValueFinder { 40 public class BedQualityD50KmValueFinder {
34 41
152 + " GROUP BY t.km" 159 + " GROUP BY t.km"
153 + " ORDER BY t.km"; 160 + " ORDER BY t.km";
154 private static final String[] SQL_BED_D50_SELECT_ALIAS = {"km", "mindate", "maxdate", "cnt", "mindepth", "maxdepth", "d50"}; 161 private static final String[] SQL_BED_D50_SELECT_ALIAS = {"km", "mindate", "maxdate", "cnt", "mindepth", "maxdepth", "d50"};
155 162
156 /** 163 /**
157 * Real linear interpolator for kms and d50 values 164 * Kms of the loaded river range
158 */ 165 */
159 private PolynomialSplineFunction interpolator; 166 private TDoubleArrayList kms;
167
168 /**
169 * D50 for each km in kms
170 */
171 private TDoubleArrayList values;
172
160 173
161 /***** METHODS *****/ 174 /***** METHODS *****/
162 175
163 /** 176 /**
164 * Returns the d50 value interpolated according to a km 177 * Returns the d50 value interpolated according to a km
165 * @throws ArgumentOutsideDomainException 178 * @return d50 (mm) of the km, or NaN
166 */ 179 */
167 public double findD50(double km) throws ArgumentOutsideDomainException { 180 public double findD50(double km) throws ArgumentOutsideDomainException {
168 return interpolator.value(km); 181 if ((kms == null) || (kms.size() == 0))
182 return Double.NaN;
183 int i = kms.binarySearch(km);
184 if (i >= 0)
185 return values.get(i);
186 i = -i - 1;
187 if ((i - 1 >= 0) && Utils.epsilonEquals(km, kms.get(i - 1), 0.0001))
188 return values.get(i - 1);
189 else if ((i >= 0) && (i <= kms.size() - 1) && Utils.epsilonEquals(km, kms.get(i), 0.0001))
190 return values.get(i);
191 else
192 return Double.NaN;
169 } 193 }
170 194
171 /** 195 /**
172 * Loads the range of the river's kms with their associated values. 196 * Loads the range of the river's kms with their associated values.
173 * @return Whether the load has been successful 197 * @return Whether the load has been successful
189 sqlQuery.setDouble("tokm", kmRange.getMaximumDouble()); 213 sqlQuery.setDouble("tokm", kmRange.getMaximumDouble());
190 sqlQuery.setDate("fromdate", dateRange.getFrom()); 214 sqlQuery.setDate("fromdate", dateRange.getFrom());
191 sqlQuery.setDate("todate", dateRange.getTo()); 215 sqlQuery.setDate("todate", dateRange.getTo());
192 @SuppressWarnings("unchecked") 216 @SuppressWarnings("unchecked")
193 final List<Object[]> rows = sqlQuery.list(); 217 final List<Object[]> rows = sqlQuery.list();
194 final double[] kms = new double[rows.size()]; 218 kms = new TDoubleArrayList();
195 final double[] values = new double[rows.size()]; 219 values = new TDoubleArrayList();
196 D50Measurement measurement; 220 D50Measurement measurement;
197 int i = -1;
198 for (Object[] row : rows) { 221 for (Object[] row : rows) {
199 measurement = new D50Measurement(row, SQL_BED_D50_SELECT_ALIAS); 222 measurement = new D50Measurement(row, SQL_BED_D50_SELECT_ALIAS);
200 i++; 223 kms.add(measurement.getKm());
201 kms[i] = measurement.getKm(); 224 values.add(measurement.getD50());
202 values[i] = measurement.getD50(); 225 log.debug(String.format("loadValues km %.3f d50(mm) %.1f count %d", kms.get(kms.size()-1), values.get(values.size()-1), measurement.getCnt()));
203 log.debug(String.format("loadValues km %.3f d50(mm) %.1f count %d", kms[i], values[i], measurement.getCnt())); 226 }
204 }
205 interpolator = new LinearInterpolator().interpolate(kms, values);
206 return true; 227 return true;
207 } 228 }
208 229
209 } 230 }

http://dive4elements.wald.intevation.org