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@3552: import org.apache.log4j.Logger; sascha@3552: sascha@3187: public class Outlier sascha@3187: { sascha@3552: private static Logger log = Logger.getLogger(Outlier.class); sascha@3552: sascha@3187: public static final int MAX_ITERATIONS = 1000; sascha@3187: sascha@3187: public interface Callback { sascha@3187: sascha@3552: void initialize(Iterator good) throws MathException; sascha@3552: sascha@3187: double eval(SQ sq); sascha@3187: sascha@3187: void outlier(SQ sq); sascha@3187: sascha@3552: void remaining(SQ sq); sascha@3552: sascha@3188: void standardDeviation(double stdDev); sascha@3188: sascha@3552: void iterationFinished(); 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@3552: public static void detectOutliers( sascha@3187: Callback callback, sascha@3187: List sqs, sascha@3187: double stdDevFactor sascha@3188: ) sascha@3188: throws MathException sascha@3188: { sascha@3552: boolean debug = log.isDebugEnabled(); sascha@3552: sascha@3552: if (debug) { sascha@3552: log.debug("stdDevFactor: " + stdDevFactor); sascha@3552: } sascha@3552: 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@3552: for (int i = 0; i < MAX_ITERATIONS && data.size() > 2; ++i) { sascha@3552: sascha@3552: callback.initialize(asSQIterator(data)); 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@3552: if (debug) { sascha@3552: log.debug("accepted: " + accepted); sascha@3552: } sascha@3187: sascha@3187: for (EvalSQ esq: data) { sascha@3552: if (debug) { sascha@3552: log.debug(" value: " + Math.abs(esq.value)); sascha@3552: } sascha@3552: sascha@3187: if (Math.abs(esq.value) > accepted) { sascha@3187: callback.outlier(esq.sq); sascha@3187: } sascha@3187: else { sascha@3552: callback.remaining(esq.sq); sascha@3187: good.add(esq); sascha@3187: } sascha@3187: } sascha@3187: sascha@3552: callback.iterationFinished(); sascha@3552: sascha@3187: if (good.size() == data.size()) { sascha@3187: break; sascha@3187: } sascha@3187: sascha@3187: List tmp = good; sascha@3187: good = data; sascha@3187: data = tmp; sascha@3187: good.clear(); sascha@3187: } 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 :