rrenkert@4794: package de.intevation.flys.artifacts.math;
rrenkert@4794: 
rrenkert@4794: import java.util.List;
rrenkert@4794: 
rrenkert@4794: import org.apache.commons.math.stat.descriptive.moment.StandardDeviation;
rrenkert@4794: 
rrenkert@4794: import org.apache.log4j.Logger;
rrenkert@4794: 
rrenkert@4794: public class StdDevOutlier
rrenkert@4794: {
rrenkert@4794:     public static final double DEFAULT_FACTOR = 3;
rrenkert@4794: 
rrenkert@4794:     private static Logger log = Logger.getLogger(StdDevOutlier.class);
rrenkert@4794: 
rrenkert@4794:     protected StdDevOutlier() {
rrenkert@4794:     }
rrenkert@4794: 
rrenkert@4794:     public static Integer findOutlier(List<Double> values) {
rrenkert@4794:         return findOutlier(values, DEFAULT_FACTOR, null);
rrenkert@4794:     }
rrenkert@4794: 
teichmann@4795:     public static Integer findOutlier(
teichmann@4795:         List<Double> values,
teichmann@4816:         double       factor,
teichmann@4795:         double []    stdDevResult
teichmann@4795:     ) {
rrenkert@4794:         boolean debug = log.isDebugEnabled();
rrenkert@4794: 
rrenkert@4794:         if (debug) {
rrenkert@4794:             log.debug("factor for std dev: " + factor);
rrenkert@4794:         }
rrenkert@4794: 
rrenkert@4794:         int N = values.size();
rrenkert@4794: 
rrenkert@4794:         if (debug) {
rrenkert@4794:             log.debug("Values to check: " + N);
rrenkert@4794:         }
rrenkert@4794: 
teichmann@4795:         if (N < 3) {
rrenkert@4794:             return null;
rrenkert@4794:         }
rrenkert@4794: 
rrenkert@4794:         StandardDeviation stdDev = new StandardDeviation();
rrenkert@4794: 
rrenkert@4794:         double maxValue = -Double.MAX_VALUE;
rrenkert@4794:         int    maxIndex = -1;
teichmann@4795:         for (int i = N-1; i >= 0; --i) {
rrenkert@4794:             double value = Math.abs(values.get(i));
rrenkert@4794:             stdDev.increment(value);
rrenkert@4794:             if (value > maxValue) {
rrenkert@4794:                 maxValue = value;
teichmann@4795:                 maxIndex = i;
rrenkert@4794:             }
rrenkert@4794:         }
rrenkert@4794: 
rrenkert@4794:         double sd = stdDev.getResult();
rrenkert@4794: 
rrenkert@4794:         double accepted = factor * sd;
rrenkert@4794: 
rrenkert@4794:         if (debug) {
rrenkert@4794:             log.debug("std dev: " + stdDev);
rrenkert@4794:             log.debug("accepted: " + accepted);
rrenkert@4794:             log.debug("max value: " + maxValue);
rrenkert@4794:         }
teichmann@4795: 
rrenkert@4794:         if (stdDevResult != null) {
rrenkert@4794:             stdDevResult[0] = sd;
rrenkert@4794:         }
teichmann@4795: 
rrenkert@4794:         return maxValue > accepted ? maxIndex : null;
rrenkert@4794:     }
rrenkert@4794: }
rrenkert@4794: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :