# HG changeset patch # User Sascha L. Teichmann # Date 1375801249 -7200 # Node ID 9479cb7c8cd5651d6979dfb85fe98ff0653f87af # Parent ae419fc225b4f0ebf1dd218b9388546716f92e64 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. diff -r ae419fc225b4 -r 9479cb7c8cd5 artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java --- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Tue Aug 06 16:57:47 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/sq/Fitting.java Tue Aug 06 17:00:49 2013 +0200 @@ -9,6 +9,7 @@ package org.dive4elements.river.artifacts.model.sq; import org.dive4elements.river.artifacts.math.fitting.Function; +import org.dive4elements.river.artifacts.math.fitting.Linear; import java.util.ArrayList; import java.util.List; @@ -17,6 +18,8 @@ import org.apache.commons.math.optimization.fitting.CurveFitter; +import org.apache.commons.math.optimization.general.AbstractLeastSquaresOptimizer; +import org.apache.commons.math.optimization.general.GaussNewtonOptimizer; import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; import org.apache.log4j.Logger; @@ -24,6 +27,10 @@ public class Fitting implements Outlier.Callback { + // XXX: Hack to force linear fitting! + private static final boolean USE_NON_LINEAR_FITTING = + Boolean.getBoolean("minfo.sq.fitting.nonlinear"); + private static Logger log = Logger.getLogger(Fitting.class); public interface Callback { @@ -75,20 +82,51 @@ @Override public void initialize(List sqs) throws MathException { - LevenbergMarquardtOptimizer lmo = - new LevenbergMarquardtOptimizer(); + AbstractLeastSquaresOptimizer optimizer = getOptimizer(); - CurveFitter cf = new CurveFitter(lmo); + CurveFitter cf = new CurveFitter(optimizer); + double [] values = new double[2]; for (SQ sq: sqs) { - cf.addObservedPoint(sq.getQ(), sq.getS()); + values[0] = sq.getQ(); + values[1] = sq.getS(); + transformInputValues(values); + cf.addObservedPoint(values[0], values[1]); } coeffs = cf.fit( function, function.getInitialGuess()); + transformCoeffsBack(coeffs); + instance = function.instantiate(coeffs); - chiSqr = lmo.getChiSquare(); + chiSqr = optimizer.getChiSquare(); + } + + protected Function getFunction(Function function) { + return USE_NON_LINEAR_FITTING + ? function + : Linear.INSTANCE; + } + + protected void transformInputValues(double [] values) { + if (!USE_NON_LINEAR_FITTING) { + for (int i = 0; i < values.length; ++i) { + values[i] = Math.log(values[i]); + } + } + } + + protected AbstractLeastSquaresOptimizer getOptimizer() { + return USE_NON_LINEAR_FITTING + ? new LevenbergMarquardtOptimizer() + : new GaussNewtonOptimizer(false); + } + + protected void transformCoeffsBack(double [] coeffs) { + if (!USE_NON_LINEAR_FITTING && coeffs.length > 0) { + coeffs[0] = Math.exp(coeffs[0]); + } } @Override