CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/TrackingTools/GsfTools/src/GSUtilities.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GsfTools/interface/GSUtilities.h"
00002 
00003 #include <TMath.h>
00004 
00005 // #include <iostream>
00006 #include <cmath>
00007 
00008 #include <map>
00009 #include <functional>
00010 
00011 float
00012 GSUtilities::quantile (const float q) const
00013 {
00014   float qq = q;
00015   if (q>1) qq = 1;
00016   else if (q<0) qq = 0;
00017   //
00018   // mean and sigma of highest weight component
00019   //
00020   int iwMax(-1);
00021   float wMax(0.);
00022   for ( unsigned i=0; i<theNComp; i++ ) {
00023     if ( theWeights[i]>wMax ) {
00024       iwMax = i;
00025       wMax = theWeights[i];
00026     }
00027   }
00028   //
00029   // Find start values: begin with mean and
00030   // go towards f(x)=0 until two points on
00031   // either side are found (assumes monotonously
00032   // increasing function)
00033   //
00034   double x1(theParameters[iwMax]);
00035   double y1(cdf(x1)-qq);
00036   double dx = y1>0. ? -theErrors[iwMax] : theErrors[iwMax];
00037   double x2(x1+dx);
00038   double y2(cdf(x2)-qq);
00039   int cnt =0;
00040   while ( y1*y2>0. ) {
00041     x1 = x2;
00042     y1 = y2;
00043     x2 += dx;
00044     y2 = cdf(x2) - qq;
00045     cnt++;
00046   }
00047 //   std::cout << "(" << x1 << "," << y1 << ") / (" 
00048 //        << x2 << "," << y2 << ")" << std::endl;
00049   //
00050   // now use bisection to find final value
00051   //
00052   double x(0.);
00053   while ( true ) {
00054     // use linear interpolation
00055     x = -(x2*y1-x1*y2)/(y2-y1);
00056     double y = cdf(x) - qq;
00057 //     std::cout << x << " " << y << std::endl;
00058     if ( fabs(y)<1.e-6 )  break;
00059     if ( y*y1>0. ) {
00060       y1 = y;
00061       x1 = x;
00062     }
00063     else {
00064       y2 = y;
00065       x2 = x;
00066     }
00067   }
00068   return x;
00069 }
00070 
00071 
00072 float
00073 GSUtilities::errorHighestWeight() const
00074 {
00075         int iwMax(-1);
00076         float wMax(0.);
00077         for ( unsigned i=0; i<theNComp; i++ ) {
00078                 if ( theWeights[i]>wMax ) {
00079                         iwMax = i;
00080                         wMax = theWeights[i];
00081                 }
00082         }
00083         return theErrors[iwMax];
00084 }
00085 
00086 
00087 float
00088 GSUtilities::mode () const
00089 {
00090   //
00091   // start values = means of components
00092   //
00093   typedef std::multimap<double, double, std::greater<double> > StartMap;
00094   StartMap xStart;
00095   for ( unsigned i=0; i<theNComp; i++ ) {
00096     xStart.insert(std::pair<double,float>(pdf(theParameters[i]),
00097                                          theParameters[i]));
00098   }
00099   //
00100   // now try with each start value
00101   //
00102   typedef std::multimap<double, double, std::greater<double> > ResultMap;
00103   ResultMap xFound;
00104   for ( StartMap::const_iterator i=xStart.begin();
00105         i!=xStart.end(); i++ ) {
00106     double x = findMode((*i).second);
00107     xFound.insert(std::pair<double,double>(pdf(x),x));
00108 //     std::cout << "Started at " << (*i).second 
00109 //       << " , found " << x << std::endl;
00110   }  
00111   //
00112   // results
00113   //
00114 //   for ( ResultMap::const_iterator i=xFound.begin();
00115 //      i!=xFound.end(); i++ ) {
00116 //     std::cout << "pdf at " << (*i).second << " = " << (*i).first << std::endl;
00117 //   }
00118   return xFound.begin()->second;
00119 }
00120 
00121 double
00122 GSUtilities::findMode (const double xStart) const
00123 {
00124   //
00125   // try with Newton
00126   //
00127   double y1(0.);
00128   double x(xStart);
00129   double y2(pdf(xStart));
00130   double yd(dpdf1(xStart));
00131   int nLoop(0);
00132   if ( (y1+y2)<10*DBL_MIN )  return xStart;
00133   while ( nLoop++<20 && fabs(y2-y1)/(y2+y1)>1.e-6 ) {
00134 //     std::cout << "dy = " << y2-y1 << std::endl;
00135     double yd2 = dpdf2(x);
00136     if ( fabs(yd2)<10*DBL_MIN )  return xStart;
00137     x -= yd/dpdf2(x);
00138     yd = dpdf1(x);
00139     y1 = y2;
00140     y2 = pdf(x);
00141 //     std::cout << "New x / yd = " << x << " / " << yd << std::endl;
00142   }
00143   if ( nLoop >= 20 )  return xStart;
00144   return x;
00145 }
00146 
00147 double
00148 GSUtilities::pdf (const double& x) const
00149 {
00150   double result(0.);
00151   for ( unsigned i=0; i<theNComp; i++ )
00152     result += theWeights[i]*gauss(x,theParameters[i],theErrors[i]);
00153   return result;
00154 }
00155 
00156 double
00157 GSUtilities::cdf (const double& x) const
00158 {
00159   double result(0.);
00160   for ( unsigned i=0; i<theNComp; i++ )
00161     result += theWeights[i]*gaussInt(x,theParameters[i],theErrors[i]);
00162   return result;
00163 }
00164 
00165 double
00166 GSUtilities::dpdf1 (const double& x) const
00167 {
00168   double result(0.);
00169   for ( unsigned i=0; i<theNComp; i++ ) {
00170     double dx = (x-theParameters[i])/theErrors[i];
00171     result += -theWeights[i]*dx/theErrors[i]*
00172       gauss(x,theParameters[i],theErrors[i]);
00173   }
00174   return result;
00175 }
00176 
00177 double
00178 GSUtilities::dpdf2 (const double& x) const
00179 {
00180   double result(0.);
00181   for ( unsigned i=0; i<theNComp; i++ ) {
00182     double dx = (x-theParameters[i])/theErrors[i];
00183     result += theWeights[i]/theErrors[i]/theErrors[i]*
00184       (dx*dx-1)*gauss(x,theParameters[i],theErrors[i]);
00185   }
00186   return result;
00187 }
00188 
00189 double 
00190 GSUtilities::gauss (const double& x, const double& mean,
00191                     const double& sigma) const 
00192 {
00193   const double fNorm(1./sqrt(2*TMath::Pi()));
00194   double result(0.);
00195 
00196   double d((x-mean)/sigma);
00197   if ( fabs(d)<20. )  result = exp(-d*d/2.);
00198   result *= fNorm/sigma;
00199   return result;
00200 }
00201 
00202 double 
00203 GSUtilities::gaussInt (const double& x, const double& mean,
00204                        const double& sigma) const 
00205 {
00206   return TMath::Freq((x-mean)/sigma);
00207 }
00208 
00209 double
00210 GSUtilities::combinedMean () const
00211 {
00212   double s0(0.);
00213   double s1(0.);
00214   for ( unsigned i=0; i<theNComp; i++ ) {
00215     s0 += theWeights[i];
00216     s1 += theWeights[i]*theParameters[i];
00217   }
00218   return s1/s0;
00219 }
00220 
00221 double
00222 GSUtilities::errorCombinedMean () const
00223 {
00224   double s0(0.);
00225   for ( unsigned i=0; i<theNComp; i++ ) {
00226     s0 += theWeights[i];
00227   }
00228   return 1./(sqrt(s0));
00229 }
00230 
00231 float
00232 GSUtilities::maxWeight () const
00233 {
00234   // Look for the highest weight component
00235   //
00236   //int iwMax(-1);
00237   float wMax(0.);
00238   for ( unsigned i=0; i<theNComp; i++ ) {
00239     if ( theWeights[i]>wMax ) {
00240       //iwMax = i;
00241       wMax = theWeights[i];
00242     }
00243   }
00244   return wMax;
00245 }
00246 
00247 
00248 float
00249 GSUtilities::errorMode()
00250 {
00251         float mod = mode();
00252         float min = getMin(mod);
00253         float max = getMax(mod);
00254         int nBins = 1000;
00255         float dx = (max - min )/(float)nBins;
00256 
00257         float x1=mod, x2=mod, x1f=mod, x2f=mod;
00258         float I=0;
00259         int cnt=0;
00260         while (I<.68) {
00261                 x1 -= dx;
00262                 x2 += dx;
00263                 if (pdf(x1)>=pdf(x2)) {
00264                         x1f = x1;
00265                         x2 -= dx;
00266                 } else {
00267                         x2f = x2;
00268                         x1 += dx;
00269                 }
00270                 I = cdf(x2f) - cdf(x1f);
00271                 cnt++;
00272                 // for crazy pdf's return a crazy value
00273                 if (cnt>2500) return 100000.;
00274         }
00275         return (x2f - x1f)/2;
00276 }
00277 
00278 float GSUtilities::getMin(float x)
00279 {
00280         int cnt=0;
00281         float dx;
00282         if (fabs(x)<2) dx = .5;
00283         else dx = fabs(x)/10;
00284         while( cdf(x)>.1 && cnt<1000) {
00285                 x -= dx;
00286                 cnt++;
00287         }
00288         return x;
00289 }
00290 
00291 float GSUtilities::getMax(float x)
00292 {
00293         int cnt=0;
00294         float dx;
00295         if (fabs(x)<2) dx = .5;
00296         else dx = fabs(x)/10;
00297         while( cdf(x)<.9 && cnt<1000) {
00298                 x += dx;
00299                 cnt++;
00300         }
00301         return x;
00302 }