package util; import java.util.Vector; // TODO: Re-do the methods in this class to use arrays or something (as // the current implementation is NOT stable in Java 1.4 // TODO: Make a simpler implementation for FTest public class BasicStats { /** * Calculates the average of the vector of Double, vec. * <p> * The average is calculated for items from index(0) to * index(size-1). * <p> * A uniform probability distribution is assumed. * <p> * Adapted from wFFRunAvgConv. * * @param vec a Vector of Double values * @param size the size of the Vector the average should be calculated to * @return the average of Double values from index(0) to index(size-1) * @throws ArithmeticException if size is 0 to indicate a divide by zero */ public static double average(Vector vec, int size) throws ArithmeticException{ double sum = 0; for(int i = 0; i < size; i++){ sum += ((Double)(vec.elementAt(i))).doubleValue(); } return sum/(double)size; } /** * Calculates the variance of items in vec from index(0) to * index(size-1). * <p> * The variance calculated assumes all measurements in a population * are in vec. (Versus a random sample.) * <p> * Note that this function may not be the safest in terms of * numerical computation errors (such as roundoff, etc.) * <p> * Adapted from wFFRunAvgConv. * * @param vec a Vector of Double values * @param size the size of the Vector the variance should be calculated over * @return the variance over a population * @throws ArithmeticException if size is 0 to indicate a divide by zero */ public static double varPop(Vector vec, int size) throws ArithmeticException{ double avg = average(vec, size); double sqDist = 0; double val = 0; for(int i=0; i<size; i++){ val = ((Double)vec.elementAt(i)).doubleValue(); sqDist += (val-avg)*(val-avg); } return sqDist/size; } /** * Calculates the sample variance of items in vec from index(0) to * index(size-1). * <p> * The variance calculated assumes all measurements in a sample * are in vec. * <p> * Note that this function may not be the safest in terms of * numerical computation errors (such as roundoff, etc.) * <p> * Adapted from wFFRunAvgConv. * * @param vec a Vector of Double values * @param size the size of the Vector the variance should be calculated over * @return the variance over a population * @throws ArithmeticException if size is 0 to indicate a divide by zero */ public static double varSample(Vector vec, int size) throws ArithmeticException{ double avg = average(vec, size); double sqDist = 0; double val = 0; for(int i=0; i<size; i++){ val = ((Double)vec.elementAt(i)).doubleValue(); sqDist += (val-avg)*(val-avg); } return sqDist/ (size-1); } /** * Returns the subvector of vec that lies between the specified indices. * <p> * Adapted from wFFRunAvgConv. * * @param vec the Vector * @param startIndex the starting index (inclusive) * @param endIndex the ending index (inclusive) * @return the subvector of vec between startIndex and endIndex inclusive */ public static Vector subVec(Vector vec, int startIndex, int endIndex){ Vector temp = new Vector(endIndex-startIndex); for(int i=0; i<=(endIndex-startIndex); i++){ temp.add(vec.elementAt(startIndex+i)); } if(Globals.isDebug)System.out.println("subVec: " + temp.toString()); return temp; } /** * Gets the averages of each subwindow. * <p> * This looks at the <code>numIntervals</code> sub-windows of size interval * in the range [startIndex, startIndex+numIntervals*interval) * <p> * Adapted from wFFRunAvgConv. * * @param vec the Vector of Double to test matching averages in * @param startIndex the start index of the first subvector * @param interval the size of the subvectors * @param numIntervals the number of intervals * @return the averages * @throws IndexOutOfBoundsException */ public static Vector getConsecAvg(Vector vec, int startIndex, int interval, int numIntervals) throws IndexOutOfBoundsException{ // If start index is negative if(startIndex < 0){ throw new IndexOutOfBoundsException("[startIndex="+startIndex+"] < 0"); } // If number of intervals is < 1, fire off an exception if(numIntervals < 1){ throw new IllegalArgumentException("Number of intervals ("+numIntervals+") is too small."); } // If start index is out of bounds, fire off an exception if(startIndex >= vec.size()){ throw new IndexOutOfBoundsException("[startIndex=" + startIndex + "]>=[vec.size()=" + vec.size()+"]"); } // See if start + 2*interval is actually possible to measure, if not if(startIndex + numIntervals*interval > vec.size()){ throw new IndexOutOfBoundsException("[startIndex("+startIndex+")+numIntervals*interval("+interval+")=" + (startIndex+numIntervals*interval)+"]>[vec.size()="+vec.size()+"]"); } Vector averages = new Vector(); Vector subVectors = new Vector(); // Vector that stores vectors // get subvectors for(int i=0; i<numIntervals; i++){ subVectors.add(i, subVec(vec, startIndex+interval*i, startIndex+interval*(i+1)-1)); } // get averages for(int i=0; i<numIntervals; i++){ averages.add(i, new Double(average((Vector)subVectors.elementAt(i), interval))); } return averages; } /** * Gets the population variance of each subwindow. * <p> * This looks at the <code>numIntervals</code> sub-windows of size interval * in the range [startIndex, startIndex+numIntervals*interval) * <p> * Adapted from wFFRunAvgConv. * * @param vec the Vector to test matching averages in * @param startIndex the start index of the first subvector * @param interval the size of the subvectors * @param numIntervals the number of intervals * @return the variances * @throws IndexOutOfBoundsException */ public static Vector getConsecVarPop(Vector vec, int startIndex, int interval, int numIntervals) throws IndexOutOfBoundsException{ // If start index is negative if(startIndex < 0){ throw new IndexOutOfBoundsException("[startIndex="+startIndex+"] < 0"); } // If number of intervals is < 1, fire off an exception if(numIntervals < 1){ throw new IllegalArgumentException("Number of intervals ("+numIntervals+") is too small."); } // If start index is out of bounds, fire off an exception if(startIndex >= vec.size()){ throw new IndexOutOfBoundsException("[startIndex=" + startIndex + "]>=[vec.size()=" + vec.size()+"]"); } // See if start + 2*interval is actually possible to measure, if not if(startIndex + numIntervals*interval > vec.size()){ throw new IndexOutOfBoundsException("[startIndex("+startIndex+")+numIntervals*interval("+interval+")=" + (startIndex+numIntervals*interval)+"]>[vec.size()="+vec.size()+"]"); } Vector variances = new Vector(); Vector subVectors = new Vector(); // vector of vectors // get subvectors for(int i=0; i<numIntervals; i++){ subVectors.add(i, subVec(vec, startIndex+interval*i, startIndex+interval*(i+1)-1)); } // get averages for(int i=0; i<numIntervals; i++){ variances.add(i, new Double(varPop((Vector)subVectors.elementAt(i), interval))); } return variances; } /** * Gets the population variance of each subwindow. * <p> * This looks at the <code>numIntervals</code> sub-windows of size interval * in the range [startIndex, startIndex+numIntervals*interval) * <p> * Adapted from wFFRunAvgConv. * * @param vec the Vector to test matching averages in * @param startIndex the start index of the first subvector * @param interval the size of the subvectors * @param numIntervals the number of intervals * @return the variances * @throws IndexOutOfBoundsException */ public static Vector getConsecVarSample(Vector vec, int startIndex, int interval, int numIntervals) throws IndexOutOfBoundsException{ // If start index is negative if(startIndex < 0){ throw new IndexOutOfBoundsException("[startIndex="+startIndex+"] < 0"); } // If number of intervals is < 1, fire off an exception if(numIntervals < 1){ throw new IllegalArgumentException("Number of intervals ("+numIntervals+") is too small."); } // If start index is out of bounds, fire off an exception if(startIndex >= vec.size()){ throw new IndexOutOfBoundsException("[startIndex=" + startIndex + "]>=[vec.size()=" + vec.size()+"]"); } // See if start + 2*interval is actually possible to measure, if not if(startIndex + numIntervals*interval > vec.size()){ throw new IndexOutOfBoundsException("[startIndex("+startIndex+")+numIntervals*interval("+interval+")=" + (startIndex+numIntervals*interval)+"]>[vec.size()="+vec.size()+"]"); } Vector variances = new Vector(); Vector subVectors = new Vector(); // vector of vectors // get subvectors for(int i=0; i<numIntervals; i++){ subVectors.add(i, subVec(vec, startIndex+interval*i, startIndex+interval*(i+1)-1)); } // get averages for(int i=0; i<numIntervals; i++){ variances.add(i, new Double(varSample((Vector)subVectors.elementAt(i), interval))); } return variances; } /** * Returns the FTest value of the Double values between * [startIndex, startIndex+interval*numIntervals) * <p> * Adapted from wFFRunAvgConv. * * @param vec * @param startIndex * @param interval * @param numIntervals * @return */ static public double basicFTest(Vector vec, int startIndex, int interval, int numIntervals){ double result; Vector variances = getConsecVarSample(vec, startIndex, interval, numIntervals); Vector averages = getConsecAvg(vec, startIndex, interval, numIntervals); double grandVariance = average(variances, numIntervals); double betweenVariance = varSample(averages, numIntervals); result = betweenVariance / grandVariance; return result; } }