changeset 3566:8d0f06b76e09

S/Q relation: Fixed flys/issue748 flys-artifacts/trunk@5164 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Wed, 01 Aug 2012 10:19:45 +0000
parents b136113dad53
children 572384206fe0
files flys-artifacts/ChangeLog flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java
diffstat 3 files changed, 44 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/flys-artifacts/ChangeLog	Tue Jul 31 16:46:36 2012 +0000
+++ b/flys-artifacts/ChangeLog	Wed Aug 01 10:19:45 2012 +0000
@@ -1,3 +1,11 @@
+2012-08-01	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
+
+	Fix for flys/issue748
+
+	* src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java,
+	  src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java:
+	  Only remove one data point per outlier removal iteration.
+
 2012-07-31	Sascha L. Teichmann	<sascha.teichmann@intevation.de>
 
 	* src/main/java/de/intevation/flys/artifacts/math/Outlier.java:
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java	Tue Jul 31 16:46:36 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Fitting.java	Wed Aug 01 10:19:45 2012 +0000
@@ -35,18 +35,12 @@
 
     protected de.intevation.flys.artifacts.math.Function instance;
 
-    protected List<SQ> remainings;
-    protected List<SQ> outliers;
-
-    protected double standardDeviation;
     protected double stdDevFactor;
     protected double chiSqr;
 
     protected Callback callback;
 
     public Fitting() {
-        remainings = new ArrayList<SQ>();
-        outliers   = new ArrayList<SQ>();
     }
 
     public Fitting(Function function, double stdDevFactor) {
@@ -72,14 +66,13 @@
     }
 
     @Override
-    public void initialize(Iterator<SQ> good) throws MathException {
+    public void initialize(List<SQ> sqs) throws MathException {
 
         LevenbergMarquardtOptimizer lmo =
             new LevenbergMarquardtOptimizer();
 
         CurveFitter cf = new CurveFitter(lmo);
-        while (good.hasNext()) {
-            SQ sq = good.next();
+        for (SQ sq: sqs) {
             cf.addObservedPoint(sq.getQ(), sq.getS());
         }
 
@@ -89,7 +82,6 @@
         instance = function.instantiate(coeffs);
 
         chiSqr = lmo.getChiSquare();
-
     }
 
     @Override
@@ -99,26 +91,15 @@
     }
 
     @Override
-    public void outlier(SQ sq) {
-        outliers.add(sq);
-    }
-
-    @Override
-    public void remaining(SQ sq) {
-        remainings.add(sq);
-    }
-
-    @Override
-    public void standardDeviation(double standardDeviation) {
-        this.standardDeviation = standardDeviation;
-    }
-
-    @Override
-    public void iterationFinished() {
+    public void iterationFinished(
+        double   standardDeviation,
+        SQ       outlier,
+        List<SQ> remainings
+    ) {
         if (log.isDebugEnabled()) {
             log.debug("iterationFinished ----");
             log.debug(" num remainings: " + remainings.size());
-            log.debug(" num outliers: " + outliers.size());
+            log.debug(" has outlier: " + outlier != null);
             log.debug(" standardDeviation: " + standardDeviation);
             log.debug(" Chi^2: " + chiSqr);
             log.debug("---- iterationFinished");
@@ -126,11 +107,9 @@
         callback.afterIteration(
             coeffs,
             remainings.toArray(new SQ[remainings.size()]),
-            outliers.toArray(new SQ[outliers.size()]),
+            outlier != null ? new SQ [] { outlier} : new SQ [] {},
             standardDeviation,
             chiSqr);
-        remainings.clear();
-        outliers.clear();
     }
 
     protected static final List<SQ> onlyValid(List<SQ> sqs) {
--- a/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java	Tue Jul 31 16:46:36 2012 +0000
+++ b/flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java	Wed Aug 01 10:19:45 2012 +0000
@@ -14,33 +14,19 @@
 {
     private static Logger log = Logger.getLogger(Outlier.class);
 
-    public static final int MAX_ITERATIONS = 1000;
-
     public interface Callback {
 
-        void initialize(Iterator<SQ> good) throws MathException;
+        void initialize(List<SQ> sqs) throws MathException;
 
         double eval(SQ sq);
 
-        void outlier(SQ sq);
-
-        void remaining(SQ sq);
-
-        void standardDeviation(double stdDev);
-
-        void iterationFinished();
+        void iterationFinished(
+            double   stdDev,
+            SQ       outlier,
+            List<SQ> remaining);
 
     } // interface Callback
 
-    private static final class EvalSQ {
-        protected SQ     sq;
-        protected double value;
-
-        public EvalSQ(SQ sq) {
-            this.sq = sq;
-        }
-    } // class EvalSQ
-
     public static void detectOutliers(
         Callback callback,
         List<SQ> sqs,
@@ -54,79 +40,46 @@
             log.debug("stdDevFactor: " + stdDevFactor);
         }
 
-        List<EvalSQ> data = new ArrayList<EvalSQ>(sqs.size());
+        List<SQ> data = new ArrayList<SQ>(sqs);
 
-        for (SQ sq: sqs) {
-            data.add(new EvalSQ(sq));
-        }
+        while (data.size() > 2) {
 
-        List<EvalSQ> good = new ArrayList<EvalSQ>(sqs.size());
-
-        for (int i = 0; i < MAX_ITERATIONS && data.size() > 2; ++i) {
-
-            callback.initialize(asSQIterator(data));
+            callback.initialize(data);
 
             StandardDeviation stdDev = new StandardDeviation();
 
-            for (EvalSQ esq: data) {
-                stdDev.increment(esq.value = callback.eval(esq.sq));
+            double maxValue = -Double.MAX_VALUE;
+            int    maxIndex = -1;
+
+            for (int i = data.size()-1; i >= 0; --i) {
+                double value = Math.abs(callback.eval(data.get(i)));
+                stdDev.increment(value);
+                if (value > maxValue) {
+                    maxValue = value;
+                    maxIndex = i;
+                }
             }
 
             double sd = stdDev.getResult();
 
-            callback.standardDeviation(sd);
-
             double accepted = stdDevFactor * sd;
 
             if (debug) {
+                log.debug("std dev: " + stdDev);
                 log.debug("accepted: " + accepted);
-            }
-
-            for (EvalSQ esq: data) {
-                if (debug) {
-                    log.debug(" value: " + Math.abs(esq.value));
-                }
-
-                if (Math.abs(esq.value) > accepted) {
-                    callback.outlier(esq.sq);
-                }
-                else {
-                    callback.remaining(esq.sq);
-                    good.add(esq);
-                }
-            }
-
-            callback.iterationFinished();
-
-            if (good.size() == data.size()) {
-                break;
+                log.debug("max value: " + maxValue);
             }
 
-            List<EvalSQ> tmp = good;
-            good = data;
-            data = tmp;
-            good.clear();
-        }
-    }
+            SQ outlier = maxValue > accepted
+                ? data.remove(maxIndex)
+                : null;
 
-    protected static Iterator<SQ> asSQIterator(List<EvalSQ> esqs) {
-        final Iterator<EvalSQ> parent = esqs.iterator();
-        return new Iterator<SQ>() {
-            @Override
-            public boolean hasNext() {
-                return parent.hasNext();
-            }
+            callback.iterationFinished(sd, outlier, data);
 
-            @Override
-            public SQ next() {
-                return parent.next().sq;
+            if (outlier == null) {
+                break;
             }
-
-            @Override
-            public void remove() {
-                throw new UnsupportedOperationException();
-            }
-        };
+        }
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org