001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.feature.visitor;
017:
018: import org.geotools.feature.Feature;
019: import org.opengis.filter.expression.Expression;
020:
021: /**
022: * Determines the standard deviation.
023: *
024: * ----------------------------
025: * | 1 ---
026: * Std dev = | ___ \ ( x - mean ) ^ 2
027: * \| N /__
028: *
029: * aka std dev = sqrt((sum((x-mean)^2))/N) where N is the number of samples
030: *
031: * @author Cory Horner, Refractions Research Inc.
032: *
033: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/feature/visitor/StandardDeviationVisitor.java $
034: */
035: public class StandardDeviationVisitor implements FeatureCalc {
036: private Expression expr;
037: private int count = 0;
038: private double deviationSquaredSum = 0;
039: private double average = 0;
040:
041: boolean visited = false;
042: int countNull = 0;
043: int countNaN = 0;
044:
045: public StandardDeviationVisitor(Expression expr, double average) {
046: this .expr = expr;
047: this .average = average;
048: //at the moment we're assuming we won't know who the feature collection is, and need the average as input
049: }
050:
051: public CalcResult getResult() {
052: return new AbstractCalcResult() {
053: public Object getValue() {
054: if (count == 0)
055: return null;
056: return new Double(Math
057: .sqrt(deviationSquaredSum / count));
058: }
059: };
060: }
061:
062: public void visit(Feature feature) {
063: Object value = expr.evaluate(feature);
064:
065: if (value == null) {
066: countNull++; // increment the null count
067: return; // don't store this value
068: }
069:
070: if (value instanceof Double) {
071: double doubleVal = ((Double) value).doubleValue();
072: if (Double.isNaN(doubleVal) || Double.isInfinite(doubleVal)) {
073: countNaN++; // increment the NaN count
074: return; // don't store NaN value
075: }
076: }
077:
078: count++;
079: deviationSquaredSum += Math.pow(average
080: - Double.parseDouble(value.toString()), 2);
081: }
082:
083: public void reset() {
084: this .count = 0;
085: this .countNull = 0;
086: this .countNaN = 0;
087: this .deviationSquaredSum = 0;
088: this .average = 0;
089: }
090:
091: /**
092: * @return the number of features which returned a NaN
093: */
094: public int getNaNCount() {
095: return countNaN;
096: }
097:
098: /**
099: * @return the number of features which returned a null
100: */
101: public int getNullCount() {
102: return countNull;
103: }
104: }
|