comparison artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java @ 6761:9479cb7c8cd5

flys/issue748: Force linear curve fitting. This is a real hack! Set the system property "minfo.sq.fitting.nonlinear" to re-enable the old behavior.
author Sascha L. Teichmann <teichmann@intevation.de>
date Tue, 06 Aug 2013 17:00:49 +0200
parents af13ceeba52a
children 48f6780c372d
comparison
equal deleted inserted replaced
6760:ae419fc225b4 6761:9479cb7c8cd5
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.river.artifacts.math.fitting.Function; 11 import org.dive4elements.river.artifacts.math.fitting.Function;
12 import org.dive4elements.river.artifacts.math.fitting.Linear;
12 13
13 import java.util.ArrayList; 14 import java.util.ArrayList;
14 import java.util.List; 15 import java.util.List;
15 16
16 import org.apache.commons.math.MathException; 17 import org.apache.commons.math.MathException;
17 18
18 import org.apache.commons.math.optimization.fitting.CurveFitter; 19 import org.apache.commons.math.optimization.fitting.CurveFitter;
19 20
21 import org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer;
22 import org.apache.commons.math.optimization.general.GaussNewtonOptimizer;
20 import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; 23 import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
21 24
22 import org.apache.log4j.Logger; 25 import org.apache.log4j.Logger;
23 26
24 public class Fitting 27 public class Fitting
25 implements Outlier.Callback 28 implements Outlier.Callback
26 { 29 {
30 // XXX: Hack to force linear fitting!
31 private static final boolean USE_NON_LINEAR_FITTING =
32 Boolean.getBoolean("minfo.sq.fitting.nonlinear");
33
27 private static Logger log = Logger.getLogger(Fitting.class); 34 private static Logger log = Logger.getLogger(Fitting.class);
28 35
29 public interface Callback { 36 public interface Callback {
30 37
31 void afterIteration( 38 void afterIteration(
73 } 80 }
74 81
75 @Override 82 @Override
76 public void initialize(List<SQ> sqs) throws MathException { 83 public void initialize(List<SQ> sqs) throws MathException {
77 84
78 LevenbergMarquardtOptimizer lmo = 85 AbstractLeastSquaresOptimizer optimizer = getOptimizer();
79 new LevenbergMarquardtOptimizer();
80 86
81 CurveFitter cf = new CurveFitter(lmo); 87 CurveFitter cf = new CurveFitter(optimizer);
88 double [] values = new double[2];
82 for (SQ sq: sqs) { 89 for (SQ sq: sqs) {
83 cf.addObservedPoint(sq.getQ(), sq.getS()); 90 values[0] = sq.getQ();
91 values[1] = sq.getS();
92 transformInputValues(values);
93 cf.addObservedPoint(values[0], values[1]);
84 } 94 }
85 95
86 coeffs = cf.fit( 96 coeffs = cf.fit(
87 function, function.getInitialGuess()); 97 function, function.getInitialGuess());
88 98
99 transformCoeffsBack(coeffs);
100
89 instance = function.instantiate(coeffs); 101 instance = function.instantiate(coeffs);
90 102
91 chiSqr = lmo.getChiSquare(); 103 chiSqr = optimizer.getChiSquare();
104 }
105
106 protected Function getFunction(Function function) {
107 return USE_NON_LINEAR_FITTING
108 ? function
109 : Linear.INSTANCE;
110 }
111
112 protected void transformInputValues(double [] values) {
113 if (!USE_NON_LINEAR_FITTING) {
114 for (int i = 0; i < values.length; ++i) {
115 values[i] = Math.log(values[i]);
116 }
117 }
118 }
119
120 protected AbstractLeastSquaresOptimizer getOptimizer() {
121 return USE_NON_LINEAR_FITTING
122 ? new LevenbergMarquardtOptimizer()
123 : new GaussNewtonOptimizer(false);
124 }
125
126 protected void transformCoeffsBack(double [] coeffs) {
127 if (!USE_NON_LINEAR_FITTING && coeffs.length > 0) {
128 coeffs[0] = Math.exp(coeffs[0]);
129 }
92 } 130 }
93 131
94 @Override 132 @Override
95 public double eval(SQ sq) { 133 public double eval(SQ sq) {
96 double s = instance.value(sq.q); 134 double s = instance.value(sq.q);

http://dive4elements.wald.intevation.org