sascha@3187: package de.intevation.flys.artifacts.model.sq; sascha@3187: sascha@3187: import java.util.ArrayList; sascha@3188: import java.util.Iterator; sascha@3187: import java.util.List; sascha@3187: sascha@3188: import org.apache.commons.math.MathException; sascha@3188: sascha@3187: import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; sascha@3187: sascha@3187: public class Outlier sascha@3187: { sascha@3187: public static final int MAX_ITERATIONS = 1000; sascha@3187: sascha@3187: public interface Callback { sascha@3187: sascha@3187: double eval(SQ sq); sascha@3187: sascha@3187: void iteration(int i); sascha@3187: sascha@3187: void outlier(SQ sq); sascha@3187: sascha@3188: void standardDeviation(double stdDev); sascha@3188: sascha@3188: void reinitialize(Iterator good) throws MathException; sascha@3188: sascha@3187: void finished(); sascha@3187: sascha@3187: } // interface Callback sascha@3187: sascha@3187: private static final class EvalSQ { sascha@3187: protected SQ sq; sascha@3187: protected double value; sascha@3187: sascha@3187: public EvalSQ(SQ sq) { sascha@3187: this.sq = sq; sascha@3187: } sascha@3187: } // class EvalSQ sascha@3187: sascha@3187: public static List detectOutliers( sascha@3187: Callback callback, sascha@3187: List sqs, sascha@3187: double stdDevFactor sascha@3188: ) sascha@3188: throws MathException sascha@3188: { sascha@3187: List data = new ArrayList(sqs.size()); sascha@3187: sascha@3187: for (SQ sq: sqs) { sascha@3187: data.add(new EvalSQ(sq)); sascha@3187: } sascha@3187: sascha@3187: List good = new ArrayList(sqs.size()); sascha@3187: sascha@3188: for (int i = 1; i <= MAX_ITERATIONS && data.size() > 2; ++i) { sascha@3187: sascha@3187: StandardDeviation stdDev = new StandardDeviation(); sascha@3187: sascha@3187: for (EvalSQ esq: data) { sascha@3187: stdDev.increment(esq.value = callback.eval(esq.sq)); sascha@3187: } sascha@3187: sascha@3188: double sd = stdDev.getResult(); sascha@3188: sascha@3188: callback.standardDeviation(sd); sascha@3188: sascha@3188: double accepted = stdDevFactor * sd; sascha@3187: sascha@3187: callback.iteration(i); sascha@3187: sascha@3187: for (EvalSQ esq: data) { sascha@3187: if (Math.abs(esq.value) > accepted) { sascha@3187: callback.outlier(esq.sq); sascha@3187: } sascha@3187: else { sascha@3187: good.add(esq); sascha@3187: } sascha@3187: } sascha@3187: sascha@3187: if (good.size() == data.size()) { sascha@3187: break; sascha@3187: } sascha@3187: sascha@3188: callback.reinitialize(asSQIterator(good)); sascha@3188: sascha@3187: List tmp = good; sascha@3187: good = data; sascha@3187: data = tmp; sascha@3187: good.clear(); sascha@3187: } sascha@3187: sascha@3187: callback.finished(); sascha@3187: sascha@3187: List result = new ArrayList(good.size()); sascha@3187: sascha@3187: for (EvalSQ esq: good) { sascha@3187: result.add(esq.sq); sascha@3187: } sascha@3187: sascha@3187: return result; sascha@3187: } sascha@3188: sascha@3188: protected static Iterator asSQIterator(List esqs) { sascha@3188: final Iterator parent = esqs.iterator(); sascha@3188: return new Iterator() { sascha@3188: @Override sascha@3188: public boolean hasNext() { sascha@3188: return parent.hasNext(); sascha@3188: } sascha@3188: sascha@3188: @Override sascha@3188: public SQ next() { sascha@3188: return parent.next().sq; sascha@3188: } sascha@3188: sascha@3188: @Override sascha@3188: public void remove() { sascha@3188: throw new UnsupportedOperationException(); sascha@3188: } sascha@3188: }; sascha@3188: } sascha@3187: } sascha@3187: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :