QGpCoreTools/StatisticalValue.h
Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 **  This file is part of QGpCoreTools.
00004 **
00005 **  This library is free software; you can redistribute it and/or
00006 **  modify it under the terms of the GNU Lesser General Public
00007 **  License as published by the Free Software Foundation; either
00008 **  version 2.1 of the License, or (at your option) any later version.
00009 **
00010 **  This file is distributed in the hope that it will be useful, but WITHOUT
00011 **  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 **  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00013 **  License for more details.
00014 **
00015 **  You should have received a copy of the GNU Lesser General Public
00016 **  License along with this library; if not, write to the Free Software
00017 **  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 **
00019 **  See http://www.geopsy.org for more information.
00020 **
00021 **  Created : 2004-10-21
00022 **  Authors :
00023 **    Marc Wathelet
00024 **    Marc Wathelet (ULg, Liège, Belgium)
00025 **    Marc Wathelet (LGIT, Grenoble, France)
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 } // namespace QGpCoreTools
00379 
00380 #endif // STATISTICALVALUE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines