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 :

http://dive4elements.wald.intevation.org