00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef STATISTICS_H
00019 #define STATISTICS_H
00020
00021 #include<odindata/data.h>
00022 #include<odindata/utils.h>
00023
00024
00030
00031
00036 struct statisticResult {
00037
00041 double min;
00042
00046 double max;
00047
00051 double mean;
00052
00056 double stdev;
00057
00061 double meandev;
00062
00066 friend STD_ostream& operator << (STD_ostream& s, statisticResult stats);
00067
00068 };
00069
00070
00072
00078 template<typename T, int N_rank>
00079 statisticResult statistics(const Array<T,N_rank>& ensemble, const Array<T,N_rank>* mask=0) {
00080 Log<OdinData> odinlog("","statistics");
00081 statisticResult result;
00082
00083 result.min=0.0;
00084 result.max=0.0;
00085 result.mean=0.0;
00086 result.stdev=0.0;
00087 result.meandev=0.0;
00088
00089
00090 if(mask && !same_shape(ensemble,*mask)) {
00091 ODINLOG(odinlog,errorLog) << "size mismatch (ensemble.shape()=" << ensemble.shape() << ") != (mask.shape()=" << mask->shape() << ")" << STD_endl;
00092 return result;
00093 }
00094
00095
00096 int n=ensemble.numElements();
00097
00098 Data<T,N_rank> ensemble_copy(ensemble);
00099
00100 int nvals=0;
00101 TinyVector<int,N_rank> index;
00102 for(int i=0; i<n; i++) {
00103 index=ensemble_copy.create_index(i);
00104 bool include=true;
00105 if(mask && (*mask)(index)==0.0) include=false;
00106 if(include) {
00107 float val=ensemble(index);
00108 result.mean+=val;
00109 nvals++;
00110 if(i==0) {
00111 result.min=result.max=val;
00112 } else {
00113 if(val<result.min) result.min=val;
00114 if(val>result.max) result.max=val;
00115 }
00116 }
00117 }
00118 result.mean=secureDivision(result.mean,double(nvals));
00119
00120 nvals=0;
00121 for(int i=0; i<n; i++) {
00122 index=ensemble_copy.create_index(i);
00123 bool include=true;
00124 if(mask && (*mask)(index)==0.0) include=false;
00125 if(include) {
00126 double diff=result.mean-ensemble(index);
00127 result.stdev+=diff*diff;
00128 nvals++;
00129 }
00130 }
00131 if(nvals>1) result.stdev=sqrt(result.stdev/double(nvals-1));
00132 else result.stdev=0.0;
00133
00134 result.meandev=result.stdev/sqrt(double(nvals));
00135
00136 return result;
00137 }
00138
00140
00145 template<typename T, int N_rank>
00146 T median(const Array<T,N_rank>& ensemble) {
00147 Data<T,N_rank> ensemble_copy(ensemble);
00148
00149 Array<T,N_rank> diff(ensemble.shape());
00150
00151 TinyVector<int,N_rank> index;
00152 for(int i=0; i<ensemble.numElements(); i++) {
00153 index=ensemble_copy.create_index(i);
00154 diff(index)=sum(fabs(ensemble-ensemble(index)));
00155 }
00156
00157 return ensemble(minIndex(diff));
00158 }
00159
00161
00167 template<typename T, int N_rank>
00168 T weightmean(const Array<T,N_rank>& ensemble, const Array<float,N_rank>& weight) {
00169 Log<OdinData> odinlog("","weightmean");
00170 T result;
00171 result=0;
00172
00173 Data<T,N_rank> ensemble_copy(ensemble);
00174
00175 if(ensemble.shape()!=weight.shape()) {
00176 ODINLOG(odinlog,errorLog) << "size mismatch (ensemble.shape()=" << ensemble.shape() << ") != (weight.shape()=" << weight.shape() << ")" << STD_endl;
00177 return result;
00178 }
00179
00180 float weightsum=0.0;
00181 TinyVector<int,N_rank> index;
00182 for(int i=0; i<ensemble_copy.numElements(); i++) {
00183 index=ensemble_copy.create_index(i);
00184 float w=fabs(weight(index));
00185 result+=w*ensemble_copy(index);
00186 weightsum+=w;
00187 }
00188 result/=weightsum;
00189
00190 return result;
00191 }
00192
00193
00197 #endif
00198