diff artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java @ 9646:0380717105ba

Implemented alternative fitting strategy for Log-Linear function.
author Gernot Belger <g.belger@bjoernsen.de>
date Mon, 02 Dec 2019 17:56:15 +0100
parents bc50ecfc58c5
children
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java	Mon Dec 02 17:21:43 2019 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/artifacts/model/fixings/Fitting.java	Mon Dec 02 17:56:15 2019 +0100
@@ -12,13 +12,10 @@
 import java.util.Date;
 import java.util.List;
 
-import org.apache.commons.math.MathException;
-import org.apache.commons.math.optimization.fitting.CurveFitter;
-import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer;
-import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
 import org.apache.log4j.Logger;
 import org.dive4elements.river.artifacts.math.GrubbsOutlier;
 import org.dive4elements.river.artifacts.math.fitting.Function;
+import org.dive4elements.river.artifacts.math.fitting.LogLinearAlternative;
 
 public class Fitting {
     private static Logger log = Logger.getLogger(Fitting.class);
@@ -28,20 +25,6 @@
         QWD create(double q, double w, double deltaW, boolean isOutlier);
     }
 
-    private static final class FittingData {
-        public final FixingColumnWithData event;
-        public final double w;
-        public final double q;
-        public final boolean isInterpolated;
-
-        public FittingData(final FixingColumnWithData event, final double w, final double q, final boolean isInterpolated) {
-            this.event = event;
-            this.w = w;
-            this.q = q;
-            this.isInterpolated = isInterpolated;
-        }
-    }
-
     private final double chiSqr;
 
     private final double[] parameters;
@@ -101,37 +84,14 @@
         final List<FittingData> outliers = new ArrayList<>(data.size());
 
         org.dive4elements.river.artifacts.math.Function instance = null;
-        LevenbergMarquardtOptimizer lmo = null;
-        double[] parameters = null;
+        Fitting fitting = null;
 
+        final IFittingOperation operation = createOperation(function);
         for (;;) {
 
-            parameters = null;
-
-            for (double tolerance = 1e-10; tolerance < 1e-1; tolerance *= 10d) {
-
-                lmo = new LevenbergMarquardtOptimizer();
-                lmo.setCostRelativeTolerance(tolerance);
-                lmo.setOrthoTolerance(tolerance);
-                lmo.setParRelativeTolerance(tolerance);
-
-                try {
-                    final CurveFitter cf = new CurveFitter(lmo);
+            fitting = operation.execute(data);
 
-                    for (final FittingData fittingData : data)
-                        cf.addObservedPoint(fittingData.q, fittingData.w);
-
-                    parameters = cf.fit(function, function.getInitialGuess());
-                    break;
-                }
-                catch (final MathException me) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("tolerance " + tolerance + " + failed.", me);
-                    }
-                }
-            }
-
-            if (parameters == null) {
+            if (fitting == null) {
                 /*
                  * log.debug("Parameters is null");
                  * for (int i = 0, N = xs.size(); i < N; ++i) {
@@ -142,6 +102,7 @@
             }
 
             // This is the parameterized function for a given km.
+            final double[] parameters = fitting.getParameters();
             instance = function.instantiate(parameters);
 
             if (!checkOutliers)
@@ -180,30 +141,24 @@
         }
 
         /*
-         * calculate dW of used values against the resulting function and add them to results , also calculate standard *
-         * deviation
+         * calculate dW of used values against the resulting function and add them to results
          */
-        final StandardDeviation stdDev = new StandardDeviation();
-        double maxQ = -Double.MAX_VALUE;
-
         for (final FittingData fittingData : data) {
 
             final QWD qwd = createQWD(fittingData, instance, false);
             qwds.add(qwd);
             resultColumns.addQWD(fittingData.event, km, qwd);
-
-            stdDev.increment(qwd.getDeltaW());
-
-            final double q = qwd.getQ();
-            if (q > maxQ)
-                maxQ = q;
         }
 
-        final double standardDeviation = stdDev.getResult();
+        return fitting;
+    }
 
-        final double chiSqr = lmo.getChiSquare();
+    private static IFittingOperation createOperation(final Function function) {
 
-        return new Fitting(parameters, standardDeviation, chiSqr, maxQ);
+        if (function instanceof LogLinearAlternative)
+            return new LogLinearFittingOperation((LogLinearAlternative) function);
+
+        return new LevenbergMarquardtFittingOperation(function);
     }
 
     private static QWD createQWD(final FittingData data, final org.dive4elements.river.artifacts.math.Function function, final boolean isOutlier) {

http://dive4elements.wald.intevation.org