001 /* 002 * $Id: Statistics.java,v 1.10 2012/04/17 15:14:18 rink Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2012 007 * Space Science and Engineering Center (SSEC) 008 * University of Wisconsin - Madison 009 * 1225 W. Dayton Street, Madison, WI 53706, USA 010 * https://www.ssec.wisc.edu/mcidas 011 * 012 * All Rights Reserved 013 * 014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and 015 * some McIDAS-V source code is based on IDV and VisAD source code. 016 * 017 * McIDAS-V is free software; you can redistribute it and/or modify 018 * it under the terms of the GNU Lesser Public License as published by 019 * the Free Software Foundation; either version 3 of the License, or 020 * (at your option) any later version. 021 * 022 * McIDAS-V is distributed in the hope that it will be useful, 023 * but WITHOUT ANY WARRANTY; without even the implied warranty of 024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 025 * GNU Lesser Public License for more details. 026 * 027 * You should have received a copy of the GNU Lesser Public License 028 * along with this program. If not, see http://www.gnu.org/licenses. 029 */ 030 package edu.wisc.ssec.mcidasv.data.hydra; 031 032 import visad.*; 033 import java.rmi.RemoteException; 034 035 import org.apache.commons.math.stat.descriptive.DescriptiveStatistics; 036 import org.apache.commons.math.stat.correlation.PearsonsCorrelation; 037 import org.apache.commons.math.stat.correlation.Covariance; 038 039 040 public class Statistics { 041 042 DescriptiveStatistics[] descriptiveStats = null; 043 double[][] values_x; 044 double[][] rngVals; 045 int rngTupLen; 046 int numPoints; 047 int[] numGoodPoints; 048 MathType statType; 049 050 PearsonsCorrelation pCorrelation = null; 051 052 053 public Statistics(FlatField fltFld) throws VisADException, RemoteException { 054 rngVals = fltFld.getValues(false); 055 rngTupLen = rngVals.length; 056 numPoints = fltFld.getDomainSet().getLength(); 057 numGoodPoints = new int[rngTupLen]; 058 059 values_x = new double[rngTupLen][]; 060 061 for (int k=0; k<rngTupLen; k++) { 062 values_x[k] = removeMissing(rngVals[k]); 063 numGoodPoints[k] = values_x[k].length; 064 } 065 066 descriptiveStats = new DescriptiveStatistics[rngTupLen]; 067 for (int k=0; k<rngTupLen; k++) { 068 descriptiveStats[k] = new DescriptiveStatistics(values_x[k]); 069 } 070 071 MathType rangeType = ((FunctionType)fltFld.getType()).getRange(); 072 073 if (rangeType instanceof RealTupleType) { 074 RealType[] rttypes = ((TupleType)rangeType).getRealComponents(); 075 if (rngTupLen > 1) { 076 statType = new RealTupleType(rttypes); 077 } 078 else { 079 statType = (RealType) rttypes[0]; 080 } 081 } 082 else if (rangeType instanceof RealType) { 083 statType = (RealType) rangeType; 084 } 085 else { 086 throw new VisADException("incoming type must be RealTupleType or RealType"); 087 } 088 089 pCorrelation = new PearsonsCorrelation(); 090 } 091 092 public int numPoints() { 093 return numPoints; 094 } 095 096 private double[] removeMissing(double[] vals) { 097 int num = vals.length; 098 int cnt = 0; 099 int[] good = new int[num]; 100 for (int k=0; k<num; k++) { 101 if ( !(Double.isNaN(vals[k])) ) { 102 good[cnt] = k; 103 cnt++; 104 } 105 } 106 107 if (cnt == num) { 108 return vals; 109 } 110 111 double[] newVals = new double[cnt]; 112 for (int k=0; k<cnt; k++) { 113 newVals[k] = vals[good[k]]; 114 } 115 116 return newVals; 117 } 118 119 private double[][] removeMissing(double[][] vals) { 120 int tupLen = vals.length; 121 double[][] newVals = new double[tupLen][]; 122 for (int k=0; k < tupLen; k++) { 123 newVals[k] = removeMissing(vals[k]); 124 } 125 return newVals; 126 } 127 128 public Data mean() throws VisADException, RemoteException { 129 double[] stats = new double[rngTupLen]; 130 for (int k=0; k<rngTupLen; k++) { 131 stats[k] = descriptiveStats[k].getMean(); 132 } 133 return makeStat(stats); 134 } 135 136 public Data geometricMean() throws VisADException, RemoteException { 137 double[] stats = new double[rngTupLen]; 138 for (int k=0; k<rngTupLen; k++) { 139 stats[k] = descriptiveStats[k].getGeometricMean(); 140 } 141 return makeStat(stats); 142 } 143 144 145 public Data max() throws VisADException, RemoteException { 146 double[] stats = new double[rngTupLen]; 147 for (int k=0; k<rngTupLen; k++) { 148 stats[k] = descriptiveStats[k].getMax(); 149 } 150 return makeStat(stats); 151 } 152 153 public Data min() throws VisADException, RemoteException { 154 double[] stats = new double[rngTupLen]; 155 for (int k=0; k<rngTupLen; k++) { 156 stats[k] = descriptiveStats[k].getMin(); 157 } 158 return makeStat(stats); 159 } 160 161 public Data median() throws VisADException, RemoteException { 162 double[] stats = new double[rngTupLen]; 163 for (int k=0; k<rngTupLen; k++) { 164 stats[k] = descriptiveStats[k].getPercentile(50.0); 165 } 166 return makeStat(stats); 167 } 168 169 public Data variance() throws VisADException, RemoteException { 170 double[] stats = new double[rngTupLen]; 171 for (int k=0; k<rngTupLen; k++) { 172 stats[k] = descriptiveStats[k].getVariance(); 173 } 174 return makeStat(stats); 175 } 176 177 public Data kurtosis() throws VisADException, RemoteException { 178 double[] stats = new double[rngTupLen]; 179 for (int k=0; k<rngTupLen; k++) { 180 stats[k] = descriptiveStats[k].getKurtosis(); 181 } 182 return makeStat(stats); 183 } 184 185 public Data standardDeviation() throws VisADException, RemoteException { 186 double[] stats = new double[rngTupLen]; 187 for (int k=0; k<rngTupLen; k++) { 188 stats[k] = descriptiveStats[k].getStandardDeviation(); 189 } 190 return makeStat(stats); 191 } 192 193 public Data skewness() throws VisADException, RemoteException { 194 double[] stats = new double[rngTupLen]; 195 for (int k=0; k<rngTupLen; k++) { 196 stats[k] = descriptiveStats[k].getSkewness(); 197 } 198 return makeStat(stats); 199 } 200 201 public Data correlation(FlatField fltFld) throws VisADException, RemoteException { 202 double[][] values_x = this.rngVals; 203 double[][] values_y = fltFld.getValues(false); 204 205 if (values_y.length != rngTupLen) { 206 throw new VisADException("both fields must have same range tuple length"); 207 } 208 209 double[] stats = new double[rngTupLen]; 210 211 for (int k=0; k<rngTupLen; k++) { 212 double[][] newVals = removeMissingAND(values_x[k], values_y[k]); 213 stats[k] = pCorrelation.correlation(newVals[0], newVals[1]); 214 } 215 216 return makeStat(stats); 217 } 218 219 private Data makeStat(double[] stats) throws VisADException, RemoteException { 220 if (statType instanceof RealType) { 221 return new Real((RealType)statType, stats[0]); 222 } 223 else if (statType instanceof RealTupleType) { 224 return new RealTuple((RealTupleType)statType, stats); 225 } 226 return null; 227 } 228 229 private double[][] removeMissingAND(double[] vals_x, double[] vals_y) { 230 int cnt = 0; 231 int[] good = new int[vals_x.length]; 232 for (int k=0; k<vals_x.length; k++) { 233 if ( !(Double.isNaN(vals_x[k])) && !(Double.isNaN(vals_y[k])) ) { 234 good[cnt] = k; 235 cnt++; 236 } 237 } 238 239 if (cnt == vals_x.length) { 240 return new double[][] {vals_x, vals_y}; 241 } 242 else { 243 double[] newVals_x = new double[cnt]; 244 double[] newVals_y = new double[cnt]; 245 for (int k=0; k<cnt; k++) { 246 newVals_x[k] = vals_x[good[k]]; 247 newVals_y[k] = vals_y[good[k]]; 248 } 249 return new double[][] {newVals_x, newVals_y}; 250 } 251 } 252 253 }