view flys-artifacts/src/main/java/de/intevation/flys/artifacts/model/sq/Outlier.java @ 3552:1df6984628c3

S/Q: Extented the result data model of the S/Q calculation to store the curve coefficients for each iteration step of the outlier elimination. flys-artifacts/trunk@5146 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 27 Jul 2012 12:36:09 +0000
parents 49fe2ed03c12
children 8d0f06b76e09
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;

import org.apache.log4j.Logger;

public class Outlier
{
    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;

        double eval(SQ sq);

        void outlier(SQ sq);

        void remaining(SQ sq);

        void standardDeviation(double stdDev);

        void iterationFinished();

    } // 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,
        double   stdDevFactor
    )
    throws MathException
    {
        boolean debug = log.isDebugEnabled();

        if (debug) {
            log.debug("stdDevFactor: " + stdDevFactor);
        }

        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 = 0; i < MAX_ITERATIONS && data.size() > 2; ++i) {

            callback.initialize(asSQIterator(data));

            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;

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

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

    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