comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/DischargeTables.java @ 3818:dc18457b1cef

merged flys-artifacts/pre2.7-2012-03-16
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:59 +0200
parents 899ca89f497e
children 02254d763bc0
comparison
equal deleted inserted replaced
2456:60ab1054069d 3818:dc18457b1cef
1 package de.intevation.flys.artifacts.model;
2
3 import java.util.List;
4 import java.util.Map;
5 import java.util.HashMap;
6 import java.util.Arrays;
7
8 import java.io.Serializable;
9
10 import org.hibernate.Session;
11 import org.hibernate.Query;
12
13 import org.apache.log4j.Logger;
14
15 import de.intevation.flys.backend.SessionHolder;
16 import de.intevation.flys.model.Gauge;
17 import de.intevation.flys.model.DischargeTable;
18 import de.intevation.flys.model.DischargeTableValue;
19
20 import gnu.trove.TDoubleArrayList;
21
22 public class DischargeTables
23 implements Serializable
24 {
25 private static Logger log = Logger.getLogger(DischargeTables.class);
26
27 public static final double DEFAULT_SCALE = 100.0;
28
29 public static final int MASTER = 0;
30
31 protected List<String> gaugeNames;
32
33 protected String riverName;
34
35 protected double scale;
36
37 protected int kind;
38
39 protected Map<String, double [][]> values;
40
41 public DischargeTables() {
42 }
43
44 public DischargeTables(String riverName, String gaugeName) {
45 this(riverName, gaugeName, MASTER);
46 }
47
48 public DischargeTables(String riverName, String gaugeName, int kind) {
49 this(riverName, new String [] { gaugeName }, kind);
50 }
51
52 public DischargeTables(String riverName, String [] gaugeNames) {
53 this(riverName, gaugeNames, MASTER);
54 }
55
56 public DischargeTables(String riverName, String [] gaugeNames, int kind) {
57 this(riverName, Arrays.asList(gaugeNames), kind);
58 }
59
60 public DischargeTables(
61 String riverName,
62 List<String> gaugeNames,
63 int kind
64 ) {
65 scale = Double.NaN;
66 this.kind = kind;
67 this.riverName = riverName;
68 this.gaugeNames = gaugeNames;
69 }
70
71 public double [][] getFirstTable() {
72 return getFirstTable(DEFAULT_SCALE);
73 }
74
75 public double [][] getFirstTable(double scale) {
76 Map<String, double [][]> values = getValues(scale);
77 for (double [][] table: values.values()) {
78 return table;
79 }
80 return null;
81 }
82
83 public Map<String, double [][]> getValues() {
84 return getValues(DEFAULT_SCALE);
85 }
86
87 public Map<String, double [][]> getValues(double scale) {
88 if (values == null || scale != this.scale) {
89 values = loadValues(scale);
90 this.scale = scale;
91 }
92 return values;
93 }
94
95 /**
96 * Returns mapping of gauge name to values.
97 */
98 protected Map<String, double [][]> loadValues(double scale) {
99 Map<String, double [][]> values = new HashMap<String, double [][]>();
100
101 Session session = SessionHolder.HOLDER.get();
102
103 Query gaugeQuery = session.createQuery(
104 "from Gauge where name=:gauge and river.name=:river");
105 gaugeQuery.setParameter("river", riverName);
106
107 for (String gaugeName: gaugeNames) {
108 gaugeQuery.setParameter("gauge", gaugeName);
109 List<Gauge> gauges = gaugeQuery.list();
110 if (gauges.isEmpty()) {
111 log.warn(
112 "no gauge '"+gaugeName+"' at river '"+riverName+"'");
113 continue;
114 }
115 Gauge gauge = gauges.get(0);
116
117 List<DischargeTable> tables = gauge.getDischargeTables();
118
119 if (tables.isEmpty()) {
120 log.warn(
121 "no discharge table for gauge '" + gaugeName + "'");
122 continue;
123 }
124
125 // TODO: Filter by time interval
126 DischargeTable table = tables.get(0);
127
128 double [][] vs = loadDischargeTableValues(table, scale);
129
130 values.put(gaugeName, vs);
131 }
132
133 return values;
134 }
135
136
137 /**
138 * @param table The discharge table
139 * @param scale The scale factor to adjust W and Q values.
140 * @param qSorted Boolean flag that is used to evaluate if the values should
141 * be sorted.
142 *
143 * @return the values of a discharge table.
144 */
145 public static double[][] loadDischargeTableValues(
146 DischargeTable table,
147 double scale
148 ) {
149 List<DischargeTableValue> dtvs = table.getDischargeTableValues();
150
151 final double [][] vs = new double[2][dtvs.size()];
152
153 int idx = 0;
154 for (DischargeTableValue dtv: dtvs) {
155 double q = dtv.getQ().doubleValue();
156 vs[0][idx] = q * scale;
157 vs[1][idx] = dtv.getW().doubleValue() * scale;
158 ++idx;
159 }
160
161 return vs;
162 }
163
164 private static final double EPSILON = 1e-5;
165
166 private static final boolean epsEquals(double a, double b) {
167 return Math.abs(a - b) < EPSILON;
168 }
169
170 private static final boolean between(double a, double b, double x) {
171 if (a > b) { double t = a; a = b; b = t; }
172 return x > a && x < b;
173 }
174
175 public static double [] getQsForW(double [][] values, double w) {
176
177 boolean debug = log.isDebugEnabled();
178
179 if (debug) {
180 log.debug("getQsForW: W = " + w);
181 }
182
183 double [] qs = values[0];
184 double [] ws = values[1];
185
186 int N = Math.min(qs.length, ws.length);
187
188 if (N == 0) {
189 if (debug) {
190 log.debug("Q(" + w + ") = []");
191 }
192 return new double [0];
193 }
194
195 TDoubleArrayList outQs = new TDoubleArrayList();
196
197 if (epsEquals(ws[0], w)) {
198 outQs.add(qs[0]);
199 }
200
201 for (int i = 1; i < N; ++i) {
202 if (epsEquals(ws[i], w)) {
203 outQs.add(qs[i]);
204 }
205 else if (between(ws[i-1], ws[i], w)) {
206 double w1 = ws[i-1];
207 double w2 = ws[i];
208 double q1 = qs[i-1];
209 double q2 = qs[i];
210
211 // q1 = m*w1 + b
212 // q2 = m*w2 + b
213 // q2 - q1 = m*(w2 - w1)
214 // m = (q2 - q1)/(w2 - w1) # w2 != w1
215 // b = q1 - m*w1
216 // w1 != w2
217
218 double m = (q2 - q1)/(w2 - w1);
219 double b = q1 - m*w1;
220 double q = w*m + b;
221
222 outQs.add(q);
223 }
224 }
225
226 double [] result = outQs.toNativeArray();
227
228 if (debug) {
229 log.debug("Q(" + w + ") = " + Arrays.toString(result));
230 }
231
232 return result;
233 }
234 }
235 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org