comparison artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java @ 6787:51eb6491c537

S/Q: Excel compat completed: Now the data is linearized before fitting. This can be prevented by setting the system property S/Q: Excel compat completed: Now the data is linearized before fitting. This can be prevented by setting the system property "minfo.sq.calcution.non.linear.fitting" to true.
author Sascha L. Teichmann <teichmann@intevation.de>
date Thu, 08 Aug 2013 18:14:38 +0200
parents b8f94e865875
children 0a5239a1e46e
comparison
equal deleted inserted replaced
6786:70b440dc5317 6787:51eb6491c537
6 * documentation coming with Dive4Elements River for details. 6 * documentation coming with Dive4Elements River for details.
7 */ 7 */
8 8
9 package org.dive4elements.river.artifacts.model.sq; 9 package org.dive4elements.river.artifacts.model.sq;
10 10
11 import org.dive4elements.artifacts.common.utils.StringUtils;
11 import org.dive4elements.river.artifacts.math.fitting.Function; 12 import org.dive4elements.river.artifacts.math.fitting.Function;
12 13
13 import java.util.ArrayList; 14 import java.util.ArrayList;
14 import java.util.List; 15 import java.util.List;
15 16
81 82
82 @Override 83 @Override
83 public void initialize(List<SQ> sqs) throws MathException { 84 public void initialize(List<SQ> sqs) throws MathException {
84 85
85 if (USE_NON_LINEAR_FITTING 86 if (USE_NON_LINEAR_FITTING
86 || function.getInitialGuess().length != 2) { 87 || function.getParameterNames().length != 2) {
87 nonLinearFitting(sqs); 88 nonLinearFitting(sqs);
88 } 89 }
89 else { 90 else {
90 linearFitting(sqs); 91 linearFitting(sqs);
91 } 92 }
92 } 93 }
93 94
94 protected void linearFitting(List<SQ> sqs) { 95 protected void linearFitting(List<SQ> sqs) {
95 96 coeffs = linearRegression(sqs);
96 coeffs = linearRegression(sqs);
97
98 instance = function.instantiate(coeffs); 97 instance = function.instantiate(coeffs);
99 } 98 }
100 99
101 protected double [] linearRegression(List<SQ> sqs) { 100 protected double [] linearRegression(List<SQ> sqs) {
102 101
102 String [] pns = function.getParameterNames();
103 double [] result = new double[pns.length];
104
105 if (sqs.size() < 2) {
106 log.debug("not enough points");
107 return result;
108 }
109
103 SimpleRegression reg = new SimpleRegression(); 110 SimpleRegression reg = new SimpleRegression();
104 111
105 int invalidPoints = 0;
106 for (SQ sq: sqs) { 112 for (SQ sq: sqs) {
107 double s = sq.getS(); 113 double s = sqView.getS(sq);
108 double q = sq.getQ(); 114 double q = sqView.getQ(sq);
109 if (s <= 0d || q <= 0d) { 115 reg.addData(q, s);
110 ++invalidPoints; 116 }
111 continue; 117
112 } 118 double m = reg.getIntercept();
113 reg.addData(Math.log(q), Math.log(s));
114 }
115
116 if (sqs.size() - invalidPoints < 2) {
117 log.debug("not enough points");
118 return new double [] { 0, 0 };
119 }
120
121 double a = Math.exp(reg.getIntercept());
122 double b = reg.getSlope(); 119 double b = reg.getSlope();
123 120
124 if (log.isDebugEnabled()) { 121 if (log.isDebugEnabled()) {
125 log.debug("invalid points: " + 122 log.debug("m: " + m);
126 invalidPoints + " (" + sqs.size() + ")");
127 log.debug("a: " + a + " (" + Math.log(a) + ")");
128 log.debug("b: " + b); 123 log.debug("b: " + b);
129 } 124 }
130 125
131 return new double [] { a, b }; 126 int mIdx = StringUtils.indexOf("m", pns);
127 int bIdx = StringUtils.indexOf("b", pns);
128
129 if (mIdx == -1 || bIdx == -1) {
130 log.error("index not found: " + mIdx + " " + bIdx);
131 return result;
132 }
133
134 result[bIdx] = m;
135 result[mIdx] = b;
136
137 return result;
132 } 138 }
133 139
134 140
135 protected void nonLinearFitting(List<SQ> sqs) throws MathException { 141 protected void nonLinearFitting(List<SQ> sqs) throws MathException {
136 142
138 new LevenbergMarquardtOptimizer(); 144 new LevenbergMarquardtOptimizer();
139 145
140 CurveFitter cf = new CurveFitter(optimizer); 146 CurveFitter cf = new CurveFitter(optimizer);
141 147
142 for (SQ sq: sqs) { 148 for (SQ sq: sqs) {
143 cf.addObservedPoint(sq.getS(), sq.getQ()); 149 cf.addObservedPoint(sqView.getQ(sq), sqView.getS(sq));
144 } 150 }
145 151
146 coeffs = cf.fit( 152 coeffs = cf.fit(
147 function, function.getInitialGuess()); 153 function, function.getInitialGuess());
148 154
177 outlier != null ? new SQ [] { outlier} : new SQ [] {}, 183 outlier != null ? new SQ [] { outlier} : new SQ [] {},
178 standardDeviation, 184 standardDeviation,
179 chiSqr); 185 chiSqr);
180 } 186 }
181 187
182 public boolean fit(List<SQ> sqs, String method, Callback callback) { 188 public boolean fit(List<SQ> sqs, String method, Callback callback) {
183 189
184 if (sqs.size() < 2) { 190 if (sqs.size() < 2) {
185 log.warn("Too less points for fitting."); 191 log.warn("Too less points for fitting.");
186 return false; 192 return false;
187 } 193 }

http://dive4elements.wald.intevation.org