comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixAnalysisCalculation.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
3 import de.intevation.artifacts.common.utils.StringUtils;
4 2
5 import de.intevation.flys.artifacts.access.FixAnalysisAccess; 3 import de.intevation.flys.artifacts.access.FixAnalysisAccess;
6 4
7 import de.intevation.flys.artifacts.math.fitting.Function; 5 import de.intevation.flys.artifacts.math.fitting.Function;
8 import de.intevation.flys.artifacts.math.fitting.FunctionFactory; 6 import de.intevation.flys.artifacts.math.fitting.FunctionFactory;
9 7
10 import de.intevation.flys.artifacts.model.CalculationResult; 8 import de.intevation.flys.artifacts.model.CalculationResult;
11 import de.intevation.flys.artifacts.model.DateRange; 9 import de.intevation.flys.artifacts.model.DateRange;
12 import de.intevation.flys.artifacts.model.FixingsColumn;
13 import de.intevation.flys.artifacts.model.FixingsColumnFactory;
14 10
15 import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter; 11 import de.intevation.flys.artifacts.model.FixingsOverview.AndFilter;
16 import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter; 12 import de.intevation.flys.artifacts.model.FixingsOverview.DateRangeFilter;
17 13
18 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter; 14 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing.Filter;
19 15
20 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing; 16 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing;
21 import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter; 17 import de.intevation.flys.artifacts.model.FixingsOverview.IdsFilter;
22 import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter; 18 import de.intevation.flys.artifacts.model.FixingsOverview.KmFilter;
23 import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter; 19 import de.intevation.flys.artifacts.model.FixingsOverview.SectorFilter;
24 import de.intevation.flys.artifacts.model.FixingsOverview.SectorRangeFilter;
25 20
26 import de.intevation.flys.artifacts.model.FixingsOverview; 21 import de.intevation.flys.artifacts.model.FixingsOverview;
27 import de.intevation.flys.artifacts.model.FixingsOverviewFactory; 22 import de.intevation.flys.artifacts.model.FixingsOverviewFactory;
28 import de.intevation.flys.artifacts.model.Parameters; 23 import de.intevation.flys.artifacts.model.Parameters;
29 import de.intevation.flys.artifacts.model.Range; 24 import de.intevation.flys.artifacts.model.Range;
30 25
31 import de.intevation.flys.utils.DateAverager; 26 import de.intevation.flys.utils.DateAverager;
32 import de.intevation.flys.utils.DoubleUtil;
33 import de.intevation.flys.utils.KMIndex; 27 import de.intevation.flys.utils.KMIndex;
34 28
35 import java.util.ArrayList; 29 import java.util.ArrayList;
36 import java.util.Date; 30 import java.util.Date;
37 import java.util.List; 31 import java.util.List;
43 public class FixAnalysisCalculation 37 public class FixAnalysisCalculation
44 extends FixCalculation 38 extends FixCalculation
45 { 39 {
46 private static Logger log = Logger.getLogger(FixAnalysisCalculation.class); 40 private static Logger log = Logger.getLogger(FixAnalysisCalculation.class);
47 41
48 public static final double EPSILON = 1e-4;
49
50 // TODO: Move to base class?
51 public static final String [] STANDARD_COLUMNS = {
52 "km", "chi_sqr", "max_q", "std-dev"
53 };
54
55 protected DateRange referencePeriod; 42 protected DateRange referencePeriod;
56 protected DateRange [] analysisPeriods; 43 protected DateRange [] analysisPeriods;
57 44
58 public FixAnalysisCalculation() { 45 public FixAnalysisCalculation() {
59 } 46 }
78 } 65 }
79 } 66 }
80 67
81 public CalculationResult calculate() { 68 public CalculationResult calculate() {
82 69
83 boolean debug = log.isDebugEnabled();
84
85 FixingsOverview overview = 70 FixingsOverview overview =
86 FixingsOverviewFactory.getOverview(river); 71 FixingsOverviewFactory.getOverview(river);
87 72
88 if (overview == null) { 73 if (overview == null) {
89 addProblem("fix.no.overview.available"); 74 addProblem("fix.no.overview.available");
98 83
99 if (hasProblems()) { 84 if (hasProblems()) {
100 return new CalculationResult(this); 85 return new CalculationResult(this);
101 } 86 }
102 87
103 final List<Column> eventColumns = getEventColumns(overview); 88 FitResult fitResult = doFitting(overview, func);
104 89
105 if (eventColumns.size() < 2) { 90 if (fitResult == null) {
106 addProblem("fix.too.less.data.columns");
107 return new CalculationResult(this); 91 return new CalculationResult(this);
108 } 92 }
109 93
110 final double [] qs = new double[eventColumns.size()];
111 final double [] ws = new double[qs.length];
112 final boolean [] interpolated = new boolean[ws.length];
113
114 Fitting.QWDFactory qwdFactory = new Fitting.QWDFactory() {
115 @Override
116 public QWD create(double q, double w) {
117 // Check all the event columns for close match
118 // and take the description and the date from meta.
119 for (int i = 0; i < qs.length; ++i) {
120 if (Math.abs(qs[i]-q) < EPSILON
121 && Math.abs(ws[i]-w) < EPSILON) {
122 Column column = eventColumns.get(i);
123 return new QWD(
124 qs[i], ws[i],
125 column.getDescription(),
126 column.getDate(),
127 interpolated[i],
128 0d);
129 }
130 }
131 log.warn("cannot find column for (" + q + ", " + w + ")");
132 return new QWD(q, w);
133 }
134 };
135
136 Fitting fitting = new Fitting(func, qwdFactory, preprocessing);
137
138 String [] parameterNames = func.getParameterNames();
139
140 Parameters results =
141 new Parameters(
142 StringUtils.join(STANDARD_COLUMNS, parameterNames));
143
144 boolean invalid = false;
145
146 double [] kms = DoubleUtil.explode(from, to, step / 1000.0);
147
148 if (debug) {
149 log.debug("number of kms: " + kms.length);
150 }
151
152 KMIndex<QW []> outliers = new KMIndex<QW []>();
153 KMIndex<QWD []> referenced = new KMIndex<QWD []>(kms.length);
154
155 int kmIndex = results.columnIndex("km");
156 int chiSqrIndex = results.columnIndex("chi_sqr");
157 int maxQIndex = results.columnIndex("max_q");
158 int stdDevIndex = results.columnIndex("std-dev");
159 int [] parameterIndices = results.columnIndices(parameterNames);
160
161 int numFailed = 0;
162
163 for (int i = 0; i < kms.length; ++i) {
164 double km = kms[i];
165
166 // Fill Qs and Ws from event columns.
167 for (int j = 0; j < ws.length; ++j) {
168 interpolated[j] = !eventColumns.get(j).getQW(km, qs, ws, j);
169 }
170
171 fitting.reset();
172
173 if (!fitting.fit(qs, ws)) {
174 ++numFailed;
175 addProblem(km, "fix.fitting.failed");
176 continue;
177 }
178
179 referenced.add(km, fitting.referencedToArray());
180
181 if (fitting.hasOutliers()) {
182 outliers.add(km, fitting.outliersToArray());
183 }
184
185 int row = results.newRow();
186 double [] values = fitting.getParameters();
187
188 results.set(row, kmIndex, km);
189 results.set(row, chiSqrIndex, fitting.getChiSquare());
190 results.set(row, stdDevIndex, fitting.getStandardDeviation());
191 results.set(row, maxQIndex, fitting.getMaxQ());
192 invalid |= results.set(row, parameterIndices, values);
193
194 if (debug) {
195 log.debug("km: "+km+" " + toString(parameterNames, values));
196 }
197 }
198
199 if (debug) {
200 log.debug("success: " + (kms.length - numFailed));
201 log.debug("failed: " + numFailed);
202 }
203
204 if (invalid) {
205 addProblem("fix.invalid.values");
206 results.removeNaNs();
207 }
208
209 KMIndex<AnalysisPeriod []> analysisPeriods = 94 KMIndex<AnalysisPeriod []> analysisPeriods =
210 calculateAnalysisPeriods(func, results, overview); 95 calculateAnalysisPeriods(
211 96 func,
212 outliers.sort(); 97 fitResult.getParameters(),
213 referenced.sort(); 98 overview);
99
214 analysisPeriods.sort(); 100 analysisPeriods.sort();
215 101
216 FixAnalysisResult fr = new FixAnalysisResult( 102 FixAnalysisResult far = new FixAnalysisResult(
217 results, 103 fitResult.getParameters(),
218 referenced, outliers, 104 fitResult.getReferenced(),
105 fitResult.getOutliers(),
219 analysisPeriods); 106 analysisPeriods);
220 107
221 return new CalculationResult(fr, this); 108 return new CalculationResult(far, this);
222 } 109 }
223 110
224 @Override 111 @Override
225 protected Filter createFilter() { 112 protected Filter createFilter() {
226 Filter ids = super.createFilter(); 113 Filter ids = super.createFilter();
391 new AnalysisPeriod[periodResults.size()])); 278 new AnalysisPeriod[periodResults.size()]));
392 } 279 }
393 280
394 return results; 281 return results;
395 } 282 }
396
397 /** Fetch meta and data columns for analysis periods. */
398 protected Column [][] getAnalysisColumns(FixingsOverview overview) {
399
400 boolean debug = log.isDebugEnabled();
401 if (debug) {
402 log.debug("number analysis periods: " + analysisPeriods.length);
403 }
404
405 Column columns [][] = new Column[analysisPeriods.length][];
406
407 Range range = new Range(from, to);
408 SectorRangeFilter sectorRangeFilter =
409 new SectorRangeFilter(qSectorStart, qSectorEnd);
410
411 FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
412
413 for (int i = 0; i < columns.length; ++i) {
414
415 // Construct filter for period.
416 DateRange period = analysisPeriods[i];
417
418 DateRangeFilter dateRangeFilter =
419 new DateRangeFilter(period.getFrom(), period.getTo());
420
421 Filter filter = new AndFilter()
422 .add(dateRangeFilter)
423 .add(sectorRangeFilter);
424
425 List<Fixing.Column> metaCols = overview.filter(range, filter);
426
427 if (debug) {
428 log.debug("number of filtered columns: " + metaCols.size());
429 }
430
431 ArrayList<Column> cols = new ArrayList<Column>(metaCols.size());
432
433 // Only use columns which have data.
434 for (Fixing.Column meta: metaCols) {
435 FixingsColumn data = fcf.getColumnData(meta);
436 if (data != null) {
437 cols.add(new Column(meta, data));
438 }
439 }
440
441 if (debug) {
442 log.debug("failed loading: " + (metaCols.size()-cols.size()));
443 }
444 columns[i] = cols.toArray(new Column[cols.size()]);
445 }
446
447 return columns;
448 }
449 } 283 }
450 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : 284 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org