view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java @ 3190:49fe2ed03c12

SQ: Refactored fitting to better fit the data types of SQResult. flys-artifacts/trunk@4805 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 26 Jun 2012 17:20:31 +0000
parents 1e46ced2bb57
children 1df6984628c3
line wrap: on
line source
package de.intevation.flys.artifacts.model.sq;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.math.MathException;

import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;

public class Outlier
{
    public static final int MAX_ITERATIONS = 1000;

    public interface Callback {

        double eval(SQ sq);

        void iteration(int i);

        void outlier(SQ sq);

        void standardDeviation(double stdDev);

        void reinitialize(Iterator<SQ> good) throws MathException;

        void finished();

    } // interface Callback

    private static final class EvalSQ {
        protected SQ     sq;
        protected double value;

        public EvalSQ(SQ sq) {
            this.sq = sq;
        }
    } // class EvalSQ

    public static SQ [] detectOutliers(
        Callback callback,
        List<SQ> sqs,
        double   stdDevFactor
    )
    throws MathException
    {
        List<EvalSQ> data = new ArrayList<EvalSQ>(sqs.size());

        for (SQ sq: sqs) {
            data.add(new EvalSQ(sq));
        }

        List<EvalSQ> good = new ArrayList<EvalSQ>(sqs.size());

        for (int i = 1; i <= MAX_ITERATIONS && data.size() > 2; ++i) {

            StandardDeviation stdDev = new StandardDeviation();

            for (EvalSQ esq: data) {
                stdDev.increment(esq.value = callback.eval(esq.sq));
            }

            double sd = stdDev.getResult();

            callback.standardDeviation(sd);

            double accepted = stdDevFactor * sd;

            callback.iteration(i);

            for (EvalSQ esq: data) {
                if (Math.abs(esq.value) > accepted) {
                    callback.outlier(esq.sq);
                }
                else {
                    good.add(esq);
                }
            }

            if (good.size() == data.size()) {
                break;
            }

            callback.reinitialize(asSQIterator(good));

            List<EvalSQ> tmp = good;
            good = data;
            data = tmp;
            good.clear();
        }

        callback.finished();

        SQ [] result = new SQ[good.size()];

        for (int i = 0; i < result.length; ++i) {
            result[i] = good.get(i).sq;
        }

        return result;
    }

    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();
            }

            @Override
            public SQ next() {
                return parent.next().sq;
            }

            @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