Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java @ 3435:262e7d7e58fe
FixA: Made curve fitting over the given calculation range reusable. Removed dead code.
flys-artifacts/trunk@5098 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sun, 22 Jul 2012 10:38:30 +0000 |
parents | 1a636be7612b |
children | e111902834d3 |
comparison
equal
deleted
inserted
replaced
3434:1a636be7612b | 3435:262e7d7e58fe |
---|---|
1 package de.intevation.flys.artifacts.model.fixings; | 1 package de.intevation.flys.artifacts.model.fixings; |
2 | 2 |
3 import de.intevation.artifacts.common.utils.StringUtils; | |
4 | |
3 import de.intevation.flys.artifacts.access.FixAccess; | 5 import de.intevation.flys.artifacts.access.FixAccess; |
6 | |
7 import de.intevation.flys.artifacts.math.fitting.Function; | |
4 | 8 |
5 import de.intevation.flys.artifacts.model.Calculation; | 9 import de.intevation.flys.artifacts.model.Calculation; |
6 import de.intevation.flys.artifacts.model.FixingsColumn; | 10 import de.intevation.flys.artifacts.model.FixingsColumn; |
7 import de.intevation.flys.artifacts.model.FixingsColumnFactory; | 11 import de.intevation.flys.artifacts.model.FixingsColumnFactory; |
8 | 12 |
10 | 14 |
11 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; | 15 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; |
12 import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; | 16 import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; |
13 | 17 |
14 import de.intevation.flys.artifacts.model.FixingsOverview; | 18 import de.intevation.flys.artifacts.model.FixingsOverview; |
19 import de.intevation.flys.artifacts.model.Parameters; | |
20 | |
21 import de.intevation.flys.utils.DoubleUtil; | |
22 import de.intevation.flys.utils.KMIndex; | |
15 | 23 |
16 import java.util.ArrayList; | 24 import java.util.ArrayList; |
17 import java.util.Date; | 25 import java.util.Date; |
18 import java.util.HashMap; | 26 import java.util.HashMap; |
19 import java.util.List; | 27 import java.util.List; |
23 | 31 |
24 public class FixCalculation | 32 public class FixCalculation |
25 extends Calculation | 33 extends Calculation |
26 { | 34 { |
27 private static Logger log = Logger.getLogger(FixCalculation.class); | 35 private static Logger log = Logger.getLogger(FixCalculation.class); |
36 | |
37 public static final double EPSILON = 1e-4; | |
38 | |
39 public static final String [] STANDARD_COLUMNS = { | |
40 "km", "chi_sqr", "max_q", "std-dev" | |
41 }; | |
42 | |
43 protected static class FitResult { | |
44 | |
45 protected Parameters parameters; | |
46 protected KMIndex<QWD []> referenced; | |
47 protected KMIndex<QW []> outliers; | |
48 | |
49 public FitResult() { | |
50 } | |
51 | |
52 public FitResult( | |
53 Parameters parameters, | |
54 KMIndex<QWD []> referenced, | |
55 KMIndex<QW []> outliers | |
56 ) { | |
57 this.parameters = parameters; | |
58 this.referenced = referenced; | |
59 this.outliers = outliers; | |
60 } | |
61 | |
62 public Parameters getParameters() { | |
63 return parameters; | |
64 } | |
65 | |
66 public KMIndex<QWD []> getReferenced() { | |
67 return referenced; | |
68 } | |
69 | |
70 public KMIndex<QW []> getOutliers() { | |
71 return outliers; | |
72 } | |
73 } // class FitResult | |
28 | 74 |
29 /** Helper class to bundle the meta information of a column | 75 /** Helper class to bundle the meta information of a column |
30 * and the real data. | 76 * and the real data. |
31 */ | 77 */ |
32 protected static class Column { | 78 protected static class Column { |
206 } | 252 } |
207 } | 253 } |
208 | 254 |
209 return columns; | 255 return columns; |
210 } | 256 } |
257 | |
258 protected FitResult doFitting(FixingsOverview overview, Function func) { | |
259 | |
260 boolean debug = log.isDebugEnabled(); | |
261 | |
262 final List<Column> eventColumns = getEventColumns(overview); | |
263 | |
264 if (eventColumns.size() < 2) { | |
265 addProblem("fix.too.less.data.columns"); | |
266 return null; | |
267 } | |
268 | |
269 final double [] qs = new double[eventColumns.size()]; | |
270 final double [] ws = new double[qs.length]; | |
271 final boolean [] interpolated = new boolean[ws.length]; | |
272 | |
273 Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() { | |
274 @Override | |
275 public QWD create(double q, double w) { | |
276 // Check all the event columns for close match | |
277 // and take the description and the date from meta. | |
278 for (int i = 0; i < qs.length; ++i) { | |
279 if (Math.abs(qs[i]-q) < EPSILON | |
280 && Math.abs(ws[i]-w) < EPSILON) { | |
281 Column column = eventColumns.get(i); | |
282 return new QWD( | |
283 qs[i], ws[i], | |
284 column.getDescription(), | |
285 column.getDate(), | |
286 interpolated[i], | |
287 0d); | |
288 } | |
289 } | |
290 log.warn("cannot find column for (" + q + ", " + w + ")"); | |
291 return new QWD(q, w); | |
292 } | |
293 }; | |
294 | |
295 Fitting fitting = new Fitting(func, qwdFactory, preprocessing); | |
296 | |
297 String [] parameterNames = func.getParameterNames(); | |
298 | |
299 Parameters results = | |
300 new Parameters( | |
301 StringUtils.join(STANDARD_COLUMNS, parameterNames)); | |
302 | |
303 boolean invalid = false; | |
304 | |
305 double [] kms = DoubleUtil.explode(from, to, step / 1000.0); | |
306 | |
307 if (debug) { | |
308 log.debug("number of kms: " + kms.length); | |
309 } | |
310 | |
311 KMIndex<QW []> outliers = new KMIndex<QW []>(); | |
312 KMIndex<QWD []> referenced = new KMIndex<QWD []>(kms.length); | |
313 | |
314 int kmIndex = results.columnIndex("km"); | |
315 int chiSqrIndex = results.columnIndex("chi_sqr"); | |
316 int maxQIndex = results.columnIndex("max_q"); | |
317 int stdDevIndex = results.columnIndex("std-dev"); | |
318 int [] parameterIndices = results.columnIndices(parameterNames); | |
319 | |
320 int numFailed = 0; | |
321 | |
322 for (int i = 0; i < kms.length; ++i) { | |
323 double km = kms[i]; | |
324 | |
325 // Fill Qs and Ws from event columns. | |
326 for (int j = 0; j < ws.length; ++j) { | |
327 interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j); | |
328 } | |
329 | |
330 fitting.reset(); | |
331 | |
332 if (!fitting.fit(qs, ws)) { | |
333 ++numFailed; | |
334 addProblem(km, "fix.fitting.failed"); | |
335 continue; | |
336 } | |
337 | |
338 referenced.add(km, fitting.referencedToArray()); | |
339 | |
340 if (fitting.hasOutliers()) { | |
341 outliers.add(km, fitting.outliersToArray()); | |
342 } | |
343 | |
344 int row = results.newRow(); | |
345 double [] values = fitting.getParameters(); | |
346 | |
347 results.set(row, kmIndex, km); | |
348 results.set(row, chiSqrIndex, fitting.getChiSquare()); | |
349 results.set(row, stdDevIndex, fitting.getStandardDeviation()); | |
350 results.set(row, maxQIndex, fitting.getMaxQ()); | |
351 invalid |= results.set(row, parameterIndices, values); | |
352 | |
353 if (debug) { | |
354 log.debug("km: "+km+" " + toString(parameterNames, values)); | |
355 } | |
356 } | |
357 | |
358 if (debug) { | |
359 log.debug("success: " + (kms.length - numFailed)); | |
360 log.debug("failed: " + numFailed); | |
361 } | |
362 | |
363 if (invalid) { | |
364 addProblem("fix.invalid.values"); | |
365 results.removeNaNs(); | |
366 } | |
367 | |
368 outliers.sort(); | |
369 referenced.sort(); | |
370 | |
371 return new FitResult( | |
372 results, | |
373 referenced, | |
374 outliers); | |
375 } | |
211 } | 376 } |
212 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : | 377 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |