Mercurial > dive4elements > river
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 } |