00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef STATISTICALVALUE_H
00030 #define STATISTICALVALUE_H
00031
00032 #include <math.h>
00033
00034 #include "XMLClass.h"
00035 #include "Global.h"
00036 #include "Number.h"
00037 #include "Value.h"
00038 #include "QGpCoreToolsDLLExport.h"
00039
00040 namespace QGpCoreTools {
00041
00042 enum MisfitType {L1, L1_Normalized, L1_LogNormalized, L1_NormalizedBySigmaOnly,
00043 L2, L2_Normalized, L2_LogNormalized, L2_NormalizedBySigmaOnly,
00044 Akaike, AkaikeFewSamples};
00045
00046 template <class numberType>
00047 class QGPCORETOOLS_EXPORT StatisticalValue : public XMLClass
00048 {
00049 public:
00050 inline StatisticalValue();
00051 inline StatisticalValue (const numberType& mean, double stddev=0.0, double weight=1.0, bool valid=true);
00052
00053 inline void operator=(const StatisticalValue& o);
00054 inline bool operator==(const StatisticalValue& o) const;
00055
00056 void setMean(const numberType& v) {_mean=v;}
00057 void setStddev(double v) {_stddev=v;}
00058 void setWeight(double v) {_weight=v; if(_weight==0.0) _valid=false;}
00059
00060 const numberType& mean() const {return _mean;}
00061 double stddev() const {return _stddev;}
00062 double weight() const {return _weight;}
00063
00064 void setValid(bool f) {_valid=f; if(_valid && _weight==0.0) _weight=1.0;}
00065 bool isValid() const {return _valid;}
00066
00067 static QString misfitTypeString(MisfitType type);
00068 static MisfitType misfitType(QString type);
00069
00070 double misfit(int& nValues, int& nData, const Value<numberType>& value, MisfitType type, double min) const;
00071
00072 inline void average(const StatisticalValue& p);
00073 protected:
00074 numberType _mean;
00075 double _stddev;
00076 double _weight;
00077 bool _valid;
00078 protected:
00079 virtual void xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const;
00080 virtual XMLMember xml_member(XML_MEMBER_ARGS);
00081 virtual bool xml_setProperty(XML_SETPROPERTY_ARGS);
00082 };
00083
00084 template <class numberType>
00085 QGPCORETOOLS_EXPORT QDataStream& operator<< (QDataStream& s, const StatisticalValue<numberType>& p);
00086 template <class numberType>
00087 QGPCORETOOLS_EXPORT QDataStream& operator>> (QDataStream& s, StatisticalValue<numberType>& p);
00088
00089 class QGPCORETOOLS_EXPORT RealStatisticalValue : public StatisticalValue<double>
00090 {
00091 public:
00092 RealStatisticalValue() : StatisticalValue<double>() {}
00093 RealStatisticalValue (const double& mean, double stddev=0.0, double weight=1.0, bool valid=true)
00094 : StatisticalValue<double>(mean, stddev, weight, valid) {}
00095
00096 virtual const QString& xml_tagName() const {return xmlRealStatisticalValueTag;}
00097 static const QString xmlRealStatisticalValueTag;
00098 };
00099
00100 class QGPCORETOOLS_EXPORT ComplexStatisticalValue : public StatisticalValue<Complex>
00101 {
00102 public:
00103 ComplexStatisticalValue() : StatisticalValue<Complex>() {}
00104 ComplexStatisticalValue (const double& mean, double stddev=0.0, double weight=1.0, bool valid=true)
00105 : StatisticalValue<Complex>(mean, stddev, weight, valid) {}
00106
00107 virtual const QString& xml_tagName() const {return xmlComplexStatisticalValueTag;}
00108 static const QString xmlComplexStatisticalValueTag;
00109 };
00110
00111 template <class numberType>
00112 inline StatisticalValue<numberType>::StatisticalValue()
00113 {
00114 TRACE;
00115 _mean=0.0;
00116 _stddev=0.0;
00117 _weight=1.0;
00118 _valid=true;
00119 }
00120
00121 template <class numberType>
00122 inline StatisticalValue<numberType>::StatisticalValue(const numberType& mean, double stddev,
00123 double weight, bool valid)
00124 {
00125 TRACE;
00126 _mean=mean;
00127 _stddev=stddev;
00128 _weight=weight;
00129 _valid=valid;
00130 }
00131
00132 template <class numberType>
00133 inline void StatisticalValue<numberType>::operator=(const StatisticalValue<numberType>& o)
00134 {
00135 TRACE;
00136 _mean=o._mean;
00137 _stddev=o._stddev;
00138 _weight=o._weight;
00139 _valid=o._valid;
00140 }
00141
00142 template <class numberType>
00143 inline bool StatisticalValue<numberType>::operator==(const StatisticalValue<numberType>& o) const
00144 {
00145 return _mean==o._mean && _stddev==o._stddev && _weight==o._weight && _valid==o._valid;
00146 }
00147
00148 template <class numberType>
00149 inline void StatisticalValue<numberType>::average(const StatisticalValue<numberType>& o)
00150 {
00151 TRACE;
00152 if(isValid()) {
00153 if(o.isValid()) {
00154 double wt=_weight+o._weight;
00155 _mean=(_mean*_weight+o._mean*o._weight)/wt;
00156 double sigma2=_weight*abs2(_mean);
00157 if(_weight>1.0)
00158 sigma2 += (_weight -1.0)* _stddev*_stddev;
00159 else
00160 sigma2 += _weight* _stddev*_stddev;
00161 sigma2 += o._weight *abs2(o._mean);
00162 if(o._weight>1.0)
00163 sigma2 += (o._weight-1.0) * o._stddev*o._stddev;
00164 else
00165 sigma2 += o._weight * o._stddev*o._stddev;
00166 sigma2 -= abs2(_mean) * wt;
00167 sigma2 /= wt-1;
00168 _stddev=::sqrt(sigma2);
00169 _weight=wt;
00170 }
00171 } else if(o.isValid()) {
00172 *this=o;
00173 }
00174 }
00175
00176 template <class numberType>
00177 void StatisticalValue<numberType>::xml_writeProperties(XML_WRITEPROPERTIES_ARGS) const
00178 {
00179 TRACE;
00180 Q_UNUSED(context);
00181 writeProperty(s,"mean",_mean);
00182 writeProperty(s,"stddev",_stddev);
00183 writeProperty(s,"weight",_weight);
00184 writeProperty(s,"valid",_valid);
00185 }
00186
00187 template <class numberType>
00188 XMLMember StatisticalValue<numberType>::xml_member(XML_MEMBER_ARGS)
00189 {
00190 TRACE;
00191 Q_UNUSED(attributes);
00192 Q_UNUSED(context);
00193 if(tag=="mean") return XMLMember(0);
00194 else if(tag=="stddev") return XMLMember(1);
00195 else if(tag=="weight") return XMLMember(2);
00196 else if(tag=="valid") return XMLMember(3);
00197 else return false;
00198 }
00199
00200 template <class numberType>
00201 bool StatisticalValue<numberType>::xml_setProperty(XML_SETPROPERTY_ARGS)
00202 {
00203 TRACE;
00204 Q_UNUSED(tag);
00205 Q_UNUSED(attributes);
00206 Q_UNUSED(context);
00207 switch (memberID) {
00208 case 0: {
00209 numberType tmp;
00210 SAFE_UNINITIALIZED(tmp, 0);
00211 _mean=content.to(tmp);
00212 }
00213 return true;
00214 case 1: _stddev=content.toDouble(); return true;
00215 case 2: _weight=content.toDouble(); return true;
00216 case 3: _valid=content.toBool(); return true;
00217 default: return false;
00218 }
00219 }
00220
00221 template <class numberType>
00222 QString StatisticalValue<numberType>::misfitTypeString(MisfitType type)
00223 {
00224 TRACE;
00225 switch (type) {
00226 case L1:
00227 return "L1";
00228 case L1_Normalized:
00229 return "L1_Normalized";
00230 case L1_LogNormalized:
00231 return "L1_LogNormalized";
00232 case L1_NormalizedBySigmaOnly:
00233 return "L1_NormalizedBySigmaOnly";
00234 case L2:
00235 return "L2";
00236 case L2_Normalized:
00237 return "L2_Normalized";
00238 case L2_LogNormalized:
00239 return "L2_LogNormalized";
00240 case L2_NormalizedBySigmaOnly:
00241 return "L2_NormalizedBySigmaOnly";
00242 case Akaike:
00243 return "Akaike";
00244 case AkaikeFewSamples:
00245 return "AkaikeFewSamples";
00246 }
00247 return QString::null;
00248 }
00249
00250 template <class numberType>
00251 MisfitType StatisticalValue<numberType>::misfitType(QString type)
00252 {
00253 TRACE;
00254 if(type.count()>1) {
00255 switch(type[1].unicode()) {
00256 case '1':
00257 if(type=="L1") return L1; else return L1_Normalized;
00258 case '2':
00259 if(type=="L2") return L2;
00260 else if(type=="L2_Normalized") return L2_Normalized;
00261 else return L2_NormalizedBySigmaOnly;
00262 case 'k':
00263 if(type=="Akaike") return Akaike; else return AkaikeFewSamples;
00264 break;
00265 default:
00266 break;
00267 }
00268 }
00269 return L2_Normalized;
00270 }
00271
00272 template <class numberType>
00273 double StatisticalValue<numberType>::misfit(int& nValues, int& nData,
00274 const Value<numberType>& val,
00275 MisfitType type, double min) const
00276 {
00277 TRACE;
00278 if(isValid()) {
00279 nData++;
00280 if(val.isValid()) {
00281 nValues++;
00282 double diff;
00283 switch (type) {
00284 case L1:
00285 diff=abs(_mean - val.value());
00286 if(diff<min) diff=min;
00287 return diff;
00288 case L1_Normalized:
00289 if(_stddev>0.0) {
00290 diff=abs((_mean - val.value())/_stddev);
00291 } else {
00292 diff=abs((_mean - val.value())/_mean);
00293 }
00294 if(diff<min) diff=min;
00295 return diff;
00296 case L1_LogNormalized:
00297 if(_stddev>1.0) {
00298 diff=abs((log(_mean/val.value()))/log(_stddev));
00299 } else {
00300 diff=abs((log(_mean/val.value()))/log(_mean));
00301 }
00302 if(diff<min) diff=min;
00303 return diff;
00304 case L1_NormalizedBySigmaOnly:
00305 if(_stddev>0.0) {
00306 diff=abs((_mean - val.value())/_stddev);
00307 } else {
00308 diff=abs(_mean - val.value());
00309 }
00310 if(diff<min) diff=min;
00311 return diff;
00312 case L2:
00313 diff=abs(_mean - val.value());
00314 if(diff<min) diff=min;
00315 return diff*diff;
00316 case L2_Normalized:
00317 if(_stddev>0.0) {
00318 diff=abs((_mean - val.value())/_stddev);
00319 } else {
00320 diff=abs((_mean - val.value())/_mean);
00321 }
00322 if(diff<min) diff=min;
00323 return diff*diff;
00324 case L2_LogNormalized:
00325 if(_stddev>1.0) {
00326 diff=abs((log(_mean/val.value()))/log(_stddev));
00327 } else {
00328 diff=abs((log(_mean/val.value()))/log(_mean));
00329 }
00330 if(diff<min) diff=min;
00331 return diff*diff;
00332 case L2_NormalizedBySigmaOnly:
00333 if(_stddev>0.0) {
00334 diff=abs((_mean - val.value())/_stddev);
00335 } else {
00336 diff=abs(_mean - val.value());
00337 }
00338 if(diff<min) diff=min;
00339 return diff*diff;
00340 case Akaike:
00341 case AkaikeFewSamples:
00342 diff=abs(_mean - val.value());
00343 if(diff<min) diff=min;
00344 return diff*diff;
00345 }
00346 return 0.0;
00347 } else {
00348 return 0.0;
00349 }
00350 } else {
00351 return 0.0;
00352 }
00353 }
00354
00355 template <class numberType>
00356 QDataStream& operator>> (QDataStream& s, StatisticalValue<numberType>& p)
00357 {
00358 TRACE;
00359 numberType m;
00360 s >> m;
00361 p.setMean(m);
00362 double v;
00363 s >> v;
00364 p.setStddev(v);
00365 s >> v;
00366 p.setWeight(v);
00367 return s;
00368 }
00369
00370 template <class numberType>
00371 QDataStream& operator<< (QDataStream& s, const StatisticalValue<numberType>& p)
00372 {
00373 TRACE;
00374 s << p.mean() << p.stddev() << p.weight();
00375 return s;
00376 }
00377
00378 }
00379
00380 #endif // STATISTICALVALUE_H