diff 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
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java	Thu Aug 08 16:19:59 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java	Thu Aug 08 18:14:38 2013 +0200
@@ -8,6 +8,7 @@
 
 package org.dive4elements.river.artifacts.model.sq;
 
+import org.dive4elements.artifacts.common.utils.StringUtils;
 import org.dive4elements.river.artifacts.math.fitting.Function;
 
 import java.util.ArrayList;
@@ -83,7 +84,7 @@
     public void initialize(List<SQ> sqs) throws MathException {
 
         if (USE_NON_LINEAR_FITTING
-        || function.getInitialGuess().length != 2) {
+        || function.getParameterNames().length != 2) {
             nonLinearFitting(sqs);
         }
         else {
@@ -92,43 +93,48 @@
     }
 
     protected void linearFitting(List<SQ> sqs) {
-
-        coeffs = linearRegression(sqs);
-
+        coeffs   = linearRegression(sqs);
         instance = function.instantiate(coeffs);
     }
 
     protected double [] linearRegression(List<SQ> sqs) {
 
+        String [] pns = function.getParameterNames();
+        double [] result = new double[pns.length];
+
+        if (sqs.size() < 2) {
+            log.debug("not enough points");
+            return result;
+        }
+
         SimpleRegression reg = new SimpleRegression();
 
-        int invalidPoints = 0;
         for (SQ sq: sqs) {
-            double s = sq.getS();
-            double q = sq.getQ();
-            if (s <= 0d || q <= 0d) {
-                ++invalidPoints;
-                continue;
-            }
-            reg.addData(Math.log(q), Math.log(s));
+            double s = sqView.getS(sq);
+            double q = sqView.getQ(sq);
+            reg.addData(q, s);
         }
 
-        if (sqs.size() - invalidPoints < 2) {
-            log.debug("not enough points");
-            return new double [] { 0, 0 };
-        }
-
-        double a = Math.exp(reg.getIntercept());
+        double m = reg.getIntercept();
         double b = reg.getSlope();
 
         if (log.isDebugEnabled()) {
-            log.debug("invalid points: " +
-                invalidPoints + " (" + sqs.size() + ")");
-            log.debug("a: " + a + " (" + Math.log(a) + ")");
+            log.debug("m: " + m);
             log.debug("b: " + b);
         }
 
-        return new double [] { a, b };
+        int mIdx = StringUtils.indexOf("m", pns);
+        int bIdx = StringUtils.indexOf("b", pns);
+
+        if (mIdx == -1 || bIdx == -1) {
+            log.error("index not found: " + mIdx + " " + bIdx);
+            return result;
+        }
+
+        result[bIdx] = m;
+        result[mIdx] = b;
+
+        return result;
     }
 
 
@@ -140,7 +146,7 @@
         CurveFitter cf = new CurveFitter(optimizer);
 
         for (SQ sq: sqs) {
-            cf.addObservedPoint(sq.getS(), sq.getQ());
+            cf.addObservedPoint(sqView.getQ(sq), sqView.getS(sq));
         }
 
         coeffs = cf.fit(
@@ -179,7 +185,7 @@
             chiSqr);
     }
 
-    public boolean fit(List<SQ> sqs, String   method, Callback callback) {
+    public boolean fit(List<SQ> sqs, String  method, Callback callback) {
 
         if (sqs.size() < 2) {
             log.warn("Too less points for fitting.");

http://dive4elements.wald.intevation.org