comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/fixings/FixCalculation.java @ 2729:a441be7f1589

Added Fix calculation. flys-artifacts/trunk@4462 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 22 May 2012 17:09:27 +0000
parents
children c1f2e792704a
comparison
equal deleted inserted replaced
2728:306b9d0f0fb3 2729:a441be7f1589
1 package de.intevation.flys.artifacts.model.fixings;
2
3 import de.intevation.flys.artifacts.FixationArtifactAccess;
4
5 import de.intevation.flys.artifacts.math.fitting.Function;
6 import de.intevation.flys.artifacts.math.fitting.FunctionFactory;
7
8 import de.intevation.flys.artifacts.model.Calculation;
9 import de.intevation.flys.artifacts.model.CalculationResult;
10 import de.intevation.flys.artifacts.model.FixingsColumn;
11 import de.intevation.flys.artifacts.model.FixingsColumnFactory;
12 import de.intevation.flys.artifacts.model.FixingsOverview;
13 import de.intevation.flys.artifacts.model.FixingsOverviewFactory;
14 import de.intevation.flys.artifacts.model.Parameters;
15
16 import de.intevation.flys.artifacts.model.FixingsOverview.Fixing;
17 import de.intevation.flys.artifacts.model.FixingsOverview.IdFilter;
18
19 import de.intevation.flys.utils.DoubleUtil;
20
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.apache.commons.math.MathException;
25
26 import org.apache.commons.math.optimization.fitting.CurveFitter;
27
28 import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
29
30 import org.apache.log4j.Logger;
31
32 public class FixCalculation
33 extends Calculation
34 {
35 private static Logger logger = Logger.getLogger(FixCalculation.class);
36
37 protected String river;
38 protected double from;
39 protected double to;
40 protected double step;
41 protected boolean preprocessing;
42 protected String function;
43 protected int [] events;
44
45 public FixCalculation() {
46 }
47
48 public FixCalculation(FixationArtifactAccess access) {
49
50 String river = access.getRiver();
51 Double from = access.getFrom();
52 Double to = access.getTo();
53 Double step = access.getStep();
54 String function = access.getFunction();
55 int [] events = access.getEvents();
56
57 if (river == null) {
58 // TODO: i18n
59 addProblem("fix.missing.river");
60 }
61
62 if (from == null) {
63 // TODO: i18n
64 addProblem("fix.missing.from");
65 }
66
67 if (to == null) {
68 // TODO: i18n
69 addProblem("fix.missing.to");
70 }
71
72 if (step == null) {
73 // TODO: i18n
74 addProblem("fix.missing.step");
75 }
76
77 if (function == null) {
78 // TODO: i18n
79 addProblem("fix.missing.function");
80 }
81
82 if (events == null || events.length < 1) {
83 // TODO: i18n
84 addProblem("fix.missing.events");
85 }
86
87 if (!hasProblems()) {
88 this.river = river;
89 this.from = from;
90 this.to = to;
91 this.step = step;
92 this.function = function;
93 this.events = events;
94 }
95 }
96
97 public CalculationResult calculate() {
98
99 FixingsOverview overview =
100 FixingsOverviewFactory.getOverview(river);
101
102 if (overview == null) {
103 addProblem("fix.no.overview.available");
104 }
105
106 Function func = FunctionFactory.getInstance()
107 .getFunction(function);
108
109 if (func == null) {
110 // TODO: i18n
111 addProblem("fix.invalid.function.name");
112 }
113
114 if (hasProblems()) {
115 return new CalculationResult(this);
116 }
117
118 FixingsColumnFactory fcf = FixingsColumnFactory.getInstance();
119
120 List<FixingsColumn> dataColumns =
121 new ArrayList<FixingsColumn>(events.length);
122
123 for (int eventId: events) {
124 IdFilter idFilter = new IdFilter(eventId);
125
126 List<Fixing.Column> columns = overview.filter(null, idFilter);
127 if (columns.isEmpty()) {
128 // TODO: i18n
129 addProblem("fix.missing.column", eventId);
130 continue;
131 }
132 FixingsColumn dataColumn = fcf.getColumnData(columns.get(0));
133 if (dataColumn == null) {
134 // TODO: i18n
135 addProblem("fix.cannot.load.data", eventId);
136 continue;
137 }
138 dataColumns.add(dataColumn);
139 }
140
141 if (dataColumns.size() < 2) {
142 // TODO: i18n
143 addProblem("fix.too.less.data.columns");
144 return new CalculationResult(this);
145 }
146
147 double [] kms = DoubleUtil.explode(from, to, step);
148
149 double [] ws = new double[dataColumns.size()];
150 double [] qs = new double[ws.length];
151
152 String [] parameterNames = func.getParameterNames();
153
154 Parameters results =
155 new Parameters(createColumnNames(parameterNames));
156
157 boolean invalid = false;
158
159 for (int i = 0; i < kms.length; ++i) {
160 double km = kms[i];
161
162 for (int j = 0; j < ws.length; ++j) {
163 FixingsColumn column = dataColumns.get(j);
164 qs[j] = column.getQ(km);
165 boolean interpolated = column.getW(km, ws, j);
166 // TODO: mark as interpolated.
167 }
168
169 // TODO: Do preprocessing here!
170 double [] parameters = fit(func, km, ws, qs);
171 if (parameters == null) { // Problems are reported already.
172 continue;
173 }
174
175 int row = results.newRow();
176
177 results.set(row, "km", km);
178 for (int j = 0; j < parameters.length; ++j) {
179 if (Double.isNaN(parameters[j])) {
180 invalid = true;
181 }
182 else {
183 results.set(row, parameterNames[j], parameters[j]);
184 }
185 }
186 // TODO: Calculate statistics, too!
187 }
188
189 if (invalid) {
190 // TODO: i18n
191 addProblem("fix.invalid.values");
192 results.removeNaNs();
193 }
194
195 // TODO: Calculate Delta W/t, too.
196 return new CalculationResult(results, this);
197 }
198
199 protected static String [] createColumnNames(String [] parameters) {
200 String [] result = new String[parameters.length + 1];
201 result[0] = "km";
202 // TODO: Add statistic columns, too.
203 System.arraycopy(parameters, 0, result, 1, parameters.length);
204 return result;
205 }
206
207 protected double [] fit(
208 Function function,
209 double km,
210 double [] ws,
211 double [] qs
212 ) {
213 LevenbergMarquardtOptimizer lmo = new LevenbergMarquardtOptimizer();
214 CurveFitter cf = new CurveFitter(lmo);
215
216 boolean missingWs = false;
217 boolean missingQs = false;
218
219 for (int i = 0; i < ws.length; ++i) {
220 boolean ignore = false;
221 if (Double.isNaN(ws[i])) {
222 ignore = true;
223 if (!missingWs) {
224 missingWs = true;
225 // TODO: i18n
226 addProblem(km, "fix.missing.w");
227 }
228 }
229 if (Double.isNaN(qs[i])) {
230 ignore = true;
231 if (!missingQs) {
232 missingQs = true;
233 // TODO: i18n
234 addProblem(km, "fix.missing.q");
235 }
236 }
237 if (!ignore) {
238 cf.addObservedPoint(ws[i], qs[i]);
239 }
240 }
241
242 try {
243 return cf.fit(function, function.getInitialGuess());
244 }
245 catch (MathException me) {
246 addProblem(km, "fix.fitting.failed");
247 }
248
249 return null;
250 }
251 }
252 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org