00001
00002 #ifdef __ICC
00003
00004
00005 #pragma warning(disable:1572)
00006 #endif
00007
00008
00009
00010
00011
00012 #include <cmath>
00013 #include <limits>
00014 #include <climits>
00015
00016
00017
00018 #include "AIDA/IHistogram1D.h"
00019 #include "AIDA/IAxis.h"
00020
00021
00022
00023 #include "GaudiUtils/HistoStats.h"
00024
00030
00031 namespace
00032 {
00033
00035 const double s_bad = -1 * std::numeric_limits<double>::max() ;
00037 const long s_long_bad = std::numeric_limits<int>::min() ;
00038
00039 }
00040
00041
00042
00043
00044
00045
00046
00047
00048 double Gaudi::Utils::HistoStats::moment
00049 ( const AIDA::IHistogram1D* histo ,
00050 const unsigned int order ,
00051 const double value )
00052 {
00053 if ( 0 == histo ) { return s_bad ; }
00054 if ( 0 == order ) { return 1.0 ; }
00055 if ( 1 == order ) { return mean( histo ) - value ; }
00056 if ( 2 == order )
00057 {
00058 const double _r = rms ( histo ) ;
00059 const double _d = value - mean ( histo ) ;
00060 return _r *_r + _d * _d ;
00061 }
00062 const double n = nEff ( histo ) ;
00063 if ( 0 >= n ) { return 0.0 ; }
00064
00065 const int _order = (int) order ;
00066
00067
00068 const AIDA::IAxis& axis = histo -> axis () ;
00069
00070 const int nBins = axis.bins() ;
00071 double result = 0 ;
00072 double weight = 0 ;
00073
00074 for ( int i = 0 ; i < nBins ; ++i )
00075 {
00076 const double lE = axis . binLowerEdge ( i ) ;
00077 const double uE = axis . binUpperEdge ( i ) ;
00078
00079 const double yBin = histo -> binHeight ( i ) ;
00080 const double xBin = 0.5 * ( lE + uE ) ;
00081
00082 weight += yBin ;
00083 result += yBin * std::pow ( xBin - value , _order ) ;
00084 }
00085 if ( 0 != weight ) { result /= weight ; }
00086 return result ;
00087 }
00088
00095
00096 double Gaudi::Utils::HistoStats::momentErr
00097 ( const AIDA::IHistogram1D* histo ,
00098 const unsigned int order )
00099 {
00100 if ( 0 == histo ) { return s_bad ; }
00101 const double n = nEff ( histo ) ;
00102 if ( 0 >= n ) { return 0.0 ; }
00103 const double a2o = moment ( histo , 2 * order ) ;
00104 const double ao = moment ( histo , order ) ;
00105 double result = a2o - ao*ao ;
00106 result /= n ;
00107 result = std::max ( 0.0 , result ) ;
00108 return std:: sqrt ( result ) ;
00109 }
00110
00111
00112
00113
00114
00115
00116
00117
00118 double Gaudi::Utils::HistoStats::centralMoment
00119 ( const AIDA::IHistogram1D* histo ,
00120 const unsigned int order )
00121 {
00122 if ( 0 == histo ) { return s_bad ; }
00123 if ( 0 == order ) { return 1.0 ; }
00124 if ( 1 == order ) { return 0.0 ; }
00125 if ( 2 == order )
00126 {
00127 const double sigma = histo->rms() ;
00128 return sigma * sigma ;
00129 }
00130
00131 return moment ( histo , order , mean ( histo ) ) ;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 double Gaudi::Utils::HistoStats::centralMomentErr
00144 ( const AIDA::IHistogram1D* histo ,
00145 const unsigned int order )
00146 {
00147 if ( 0 == histo ) { return s_bad ; }
00148 const double n = nEff ( histo ) ;
00149 if ( 0 >= n ) { return 0.0 ; }
00150 const double mu2 = centralMoment ( histo , 2 ) ;
00151 const double muo = centralMoment ( histo , order ) ;
00152 const double mu2o = centralMoment ( histo , 2 * order ) ;
00153 const double muom = centralMoment ( histo , order - 1 ) ;
00154 const double muop = centralMoment ( histo , order + 1 ) ;
00155 double result = mu2o ;
00156 result -= 2.0 * order * muom * muop ;
00157 result -= muo * muo ;
00158 result += order * order * mu2 * muom * muom ;
00159 result /= n ;
00160 result = std::max ( 0.0 , result ) ;
00161 return std:: sqrt ( result ) ;
00162 }
00163
00164
00165
00166 double Gaudi::Utils::HistoStats::skewness
00167 ( const AIDA::IHistogram1D* histo )
00168 {
00169 if ( 0 == histo ) { return s_bad ; }
00170 const double mu3 = centralMoment ( histo , 3 ) ;
00171 const double s3 = std::pow ( rms ( histo ) , 3 ) ;
00172 return ( std::fabs(s3)>0 ? mu3/s3 : 0.0 );
00173 }
00174
00175
00176
00177 double Gaudi::Utils::HistoStats::skewnessErr
00178 ( const AIDA::IHistogram1D* histo )
00179 {
00180 if ( 0 == histo ) { return s_bad ; }
00181 const double n = nEff ( histo ) ;
00182 if ( 2 > n ) { return 0.0 ; }
00183 double result = 6 ;
00184 result *= ( n - 2 ) ;
00185 result /= ( n + 1 ) * ( n + 3 ) ;
00186 return std::sqrt ( result ) ;
00187 }
00188
00189
00190
00191 double Gaudi::Utils::HistoStats::kurtosis
00192 ( const AIDA::IHistogram1D* histo )
00193 {
00194 if ( 0 == histo ) { return s_bad ; }
00195 const double mu4 = centralMoment ( histo , 4 ) ;
00196 const double s4 = std::pow ( rms ( histo ) , 4 ) ;
00197 return ( std::fabs(s4)>0 ? mu4/s4 - 3.0 : 0.0 );
00198 }
00199
00200
00201
00202 double Gaudi::Utils::HistoStats::kurtosisErr
00203 ( const AIDA::IHistogram1D* histo )
00204 {
00205 if ( 0 == histo ) { return s_bad ; }
00206 const double n = nEff ( histo ) ;
00207 if ( 3 > n ) { return 0.0 ; }
00208 double result = 24 * n ;
00209 result *= ( n - 2 ) * ( n - 3 ) ;
00210 result /= ( n + 1 ) * ( n + 1 ) ;
00211 result /= ( n + 3 ) * ( n + 5 ) ;
00212 return std::sqrt ( result ) ;
00213 }
00214
00215
00216
00217 double Gaudi::Utils::HistoStats::nEff
00218 ( const AIDA::IHistogram1D* histo )
00219 {
00220 if ( 0 == histo ) { return s_bad ; }
00221 return histo -> equivalentBinEntries () ;
00222 }
00223
00224
00225
00226 double Gaudi::Utils::HistoStats::mean
00227 ( const AIDA::IHistogram1D* histo )
00228 {
00229 if ( 0 == histo ) { return s_bad ; }
00230 return histo -> mean() ;
00231 }
00232
00233
00234
00235 double Gaudi::Utils::HistoStats::meanErr
00236 ( const AIDA::IHistogram1D* histo )
00237 {
00238 if ( 0 == histo ) { return s_bad ; }
00239 const double n = nEff ( histo ) ;
00240 return 0 >= n ? 0.0 : rms ( histo ) / std::sqrt ( n ) ;
00241 }
00242
00243
00244
00245 double Gaudi::Utils::HistoStats::rms
00246 ( const AIDA::IHistogram1D* histo )
00247 {
00248 if ( 0 == histo ) { return s_bad ; }
00249 return histo -> rms () ;
00250 }
00251
00252
00253
00254 double Gaudi::Utils::HistoStats::rmsErr
00255 ( const AIDA::IHistogram1D* histo )
00256 {
00257 if ( 0 == histo ) { return s_bad ; }
00258 const double n = nEff ( histo ) ;
00259 if ( 1 >= n ) { return 0.0 ; }
00260 double result = 2 + kurtosis ( histo ) ;
00261 result += 2.0 /( n - 1 ) ;
00262 result /= 4.0 * n ;
00263 result = std::max ( result , 0.0 ) ;
00264 return histo -> rms() * std::sqrt ( result ) ;
00265 }
00266
00267
00268
00269 double Gaudi::Utils::HistoStats::sumBinHeightErr
00270 ( const AIDA::IHistogram1D* histo )
00271 {
00272 if ( 0 == histo ) { return s_bad ; }
00273
00274 double error2 = 0 ;
00275
00276 const AIDA::IAxis& axis = histo -> axis () ;
00277
00278 const int nBins = axis.bins() ;
00279
00280 for ( int i = 0 ; i < nBins ; ++i )
00281 {
00282
00283 const double berr = histo->binError ( i ) ;
00284
00285 error2 += berr * berr ;
00286 }
00287 return std::sqrt ( error2 ) ;
00288 }
00289
00290
00291
00292 double Gaudi::Utils::HistoStats::sumAllBinHeightErr
00293 ( const AIDA::IHistogram1D* histo )
00294 {
00295 if ( 0 == histo ) { return s_bad ; }
00296
00297 const double error = sumBinHeightErr( histo ) ;
00298 if ( 0 > error ) { return s_bad ; }
00300 const double err1 = histo->binError ( AIDA::IAxis::UNDERFLOW_BIN ) ;
00301 const double err2 = histo->binError ( AIDA::IAxis::OVERFLOW_BIN ) ;
00302
00303 return std::sqrt ( error * error + err1 * err1 + err2 * err2 ) ;
00304 }
00305
00306
00307
00308 double Gaudi::Utils::HistoStats::overflowEntriesFrac
00309 ( const AIDA::IHistogram1D* histo )
00310 {
00311 if ( 0 == histo ) { return s_bad ; }
00312 const long overflow = histo -> binEntries ( AIDA::IAxis::OVERFLOW_BIN ) ;
00313 if ( 0 == overflow ) { return 0 ; }
00314 const long all = histo->allEntries() ;
00315 if ( 0 == all ) { return 0 ; }
00316 if ( 0 > all ) { return s_bad ; }
00317
00318 double _tmp = (double) overflow ;
00319 _tmp /= all ;
00320
00321 return _tmp ;
00322 }
00323
00324
00325
00326 double Gaudi::Utils::HistoStats::underflowEntriesFrac
00327 ( const AIDA::IHistogram1D* histo )
00328 {
00329 if ( 0 == histo ) { return s_bad ; }
00330 const long underflow = histo -> binEntries ( AIDA::IAxis::UNDERFLOW_BIN ) ;
00331 if ( 0 == underflow ) { return 0 ; }
00332 const long all = histo->allEntries() ;
00333 if ( 0 == all ) { return 0 ; }
00334 if ( 0 > all ) { return s_bad ; }
00335
00336 double _tmp = (double) underflow ;
00337 _tmp /= all ;
00338
00339 return _tmp ;
00340 }
00341
00342
00343
00344 double Gaudi::Utils::HistoStats::overflowIntegralFrac
00345 ( const AIDA::IHistogram1D* histo )
00346 {
00347 if ( 0 == histo ) { return s_bad ; }
00348 const double overflow = histo -> binHeight ( AIDA::IAxis::OVERFLOW_BIN ) ;
00349 if ( 0 == overflow ) { return 0 ; }
00350 const double all = histo -> sumAllBinHeights() ;
00351 if ( 0 == all ) { return 0 ; }
00352
00353 return overflow / all ;
00354 }
00355
00356
00357
00358 double Gaudi::Utils::HistoStats::underflowIntegralFrac
00359 ( const AIDA::IHistogram1D* histo )
00360 {
00361 if ( 0 == histo ) { return s_bad ; }
00362 const double underflow = histo -> binHeight ( AIDA::IAxis::UNDERFLOW_BIN ) ;
00363 if ( 0 == underflow ) { return 0 ; }
00364 const double all = histo -> sumAllBinHeights() ;
00365 if ( 0 == all ) { return 0 ; }
00366
00367 return underflow / all ;
00368 }
00369
00370
00371
00372 double Gaudi::Utils::HistoStats::overflowEntriesFracErr
00373 ( const AIDA::IHistogram1D* histo )
00374 {
00375 if ( 0 == histo ) { return s_bad ; }
00376
00377 const double overflow = histo -> binEntries ( AIDA::IAxis::OVERFLOW_BIN );
00378 const double all = histo -> allEntries () ;
00379
00380 if ( 0 > overflow || 0 >= all || overflow > all ) { return s_bad ; }
00381
00382 const double n = std::max ( overflow , 1.0 ) ;
00383 const double N = all ;
00384 const double n1 = std::max ( N - n , 1.0 ) ;
00385
00386 return std::sqrt ( n * n1 / N ) / N ;
00387 }
00388
00389
00390
00391 double Gaudi::Utils::HistoStats::underflowEntriesFracErr
00392 ( const AIDA::IHistogram1D* histo )
00393 {
00394 if ( 0 == histo ) { return s_bad ; }
00395
00396 const double underflow = histo -> binEntries ( AIDA::IAxis::UNDERFLOW_BIN );
00397 const double all = histo -> allEntries () ;
00398
00399 if ( 0 > underflow || 0 >= all || underflow > all ) { return s_bad ; }
00400
00401 const double n = std::max ( underflow , 1.0 ) ;
00402 const double N = all ;
00403 const double n1 = std::max ( N - n , 1.0 ) ;
00404
00405 return std::sqrt ( n * n1 / N ) / N ;
00406 }
00407
00408
00409
00410 double Gaudi::Utils::HistoStats::overflowIntegralFracErr
00411 ( const AIDA::IHistogram1D* histo )
00412 {
00413 if ( 0 == histo ) { return s_bad ; }
00414
00415 const double all = histo -> sumAllBinHeights () ;
00416 if ( 0 == all ) { return s_bad ; }
00417 const double overflow = histo -> binHeight ( AIDA::IAxis::OVERFLOW_BIN ) ;
00418 const double oErr = histo -> binError ( AIDA::IAxis::OVERFLOW_BIN ) ;
00419 if ( 0 > oErr ) { return s_bad ; }
00420 const double aErr = sumAllBinHeightErr ( histo ) ;
00421 if ( 0 > aErr ) { return s_bad ; }
00422
00423 double error2 = oErr * oErr ;
00424 error2 += aErr * aErr * overflow * overflow / all / all ;
00425 error2 /= all * all ;
00426
00427 return std::sqrt ( error2 ) ;
00428 }
00429
00430
00431
00432 double Gaudi::Utils::HistoStats::underflowIntegralFracErr
00433 ( const AIDA::IHistogram1D* histo )
00434 {
00435 if ( 0 == histo ) { return s_bad ; }
00436
00437 const double all = histo -> sumAllBinHeights () ;
00438 if ( 0 == all ) { return s_bad ; }
00439 const double underflow = histo -> binHeight ( AIDA::IAxis::UNDERFLOW_BIN ) ;
00440 const double oErr = histo -> binError ( AIDA::IAxis::UNDERFLOW_BIN ) ;
00441 if ( 0 > oErr ) { return s_bad ; }
00442 const double aErr = sumAllBinHeightErr ( histo ) ;
00443 if ( 0 > aErr ) { return s_bad ; }
00444
00445 double error2 = oErr * oErr ;
00446 error2 += aErr * aErr * underflow * underflow / all / all ;
00447 error2 /= all * all ;
00448
00449 return std::sqrt ( error2 ) ;
00450 }
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 long Gaudi::Utils::HistoStats::nEntries
00461 ( const AIDA::IHistogram1D* histo ,
00462 const int imax )
00463 {
00464 if ( 0 == histo ) { return s_long_bad ; }
00465 if ( 0 > imax ) { return 0 ; }
00466 long result = histo -> binEntries( AIDA::IAxis::UNDERFLOW_BIN ) ;
00467
00468
00469 const AIDA::IAxis& axis = histo -> axis () ;
00470
00471 const int nBins = axis.bins() ;
00472
00473 for ( int i = 0 ; i < nBins ; ++i )
00474 { if ( i < imax ) { result += histo->binEntries ( i ) ; } }
00475
00476 if ( nBins < imax )
00477 { result += histo -> binEntries( AIDA::IAxis::OVERFLOW_BIN ) ; }
00478
00479 return result ;
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 long Gaudi::Utils::HistoStats::nEntries
00491 ( const AIDA::IHistogram1D* histo ,
00492 const int imin ,
00493 const int imax )
00494 {
00495 if ( 0 == histo ) { return s_long_bad ; }
00496 if ( imin == imax ) { return 0 ; }
00497 if ( imax < imin ) { return nEntries ( histo , imax ,imin ) ; }
00498
00499 long result = 0 ;
00500 if ( 0 > imin )
00501 { result += histo -> binEntries( AIDA::IAxis::UNDERFLOW_BIN ) ; }
00502
00503 const AIDA::IAxis& axis = histo -> axis () ;
00504
00505 const int nBins = axis.bins() ;
00506 if ( nBins < imin ) { return 0 ; }
00507
00508 for ( int i = 0 ; i < nBins ; ++i )
00509 { if ( imin <= i && i < imax ) { result += histo->binEntries ( i ) ; } }
00510
00511 if ( nBins < imax )
00512 { result += histo -> binEntries( AIDA::IAxis::OVERFLOW_BIN ) ; }
00513
00514 return result ;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 double Gaudi::Utils::HistoStats::nEntriesFrac
00526 ( const AIDA::IHistogram1D* histo ,
00527 const int imax )
00528 {
00529 if ( 0 == histo ) { return s_bad ; }
00530
00531 const double N = histo->allEntries () ;
00532 if ( 0 >= N ) { return s_bad ; }
00533 const long n = nEntries ( histo , imax ) ;
00534 if ( 0 > n ) { return s_bad ; }
00535 if ( n > N ) { return s_bad ; }
00536
00537 return n / N ;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 double Gaudi::Utils::HistoStats::nEntriesFrac
00549 ( const AIDA::IHistogram1D* histo ,
00550 const int imin ,
00551 const int imax )
00552 {
00553 if ( 0 == histo ) { return s_bad ; }
00554 const double N = histo->allEntries () ;
00555 if ( 0 >= N ) { return s_bad ; }
00556 const long n = nEntries ( histo , imin , imax ) ;
00557 if ( 0 > n ) { return s_bad ; }
00558 if ( n > N ) { return s_bad ; }
00559
00560 return n / N ;
00561 }
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 double Gaudi::Utils::HistoStats::nEntriesFracErr
00572 ( const AIDA::IHistogram1D* histo ,
00573 const int imax )
00574 {
00575 if ( 0 == histo ) { return s_bad ; }
00576
00577 const double N = histo->allEntries () ;
00578 if ( 0 >= N ) { return s_bad ; }
00579 const long n = nEntries ( histo , imax ) ;
00580 if ( 0 > n ) { return s_bad ; }
00581 if ( n > N ) { return s_bad ; }
00582
00583 const double _n1 = std::max ( (double) n , 1.0 ) ;
00584 const double _n2 = std::max ( ( N - n ) , 1.0 ) ;
00585
00586 return std::sqrt ( _n1 * _n2 / N ) / N ;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 double Gaudi::Utils::HistoStats::nEntriesFracErr
00598 ( const AIDA::IHistogram1D* histo ,
00599 const int imin ,
00600 const int imax )
00601 {
00602 if ( 0 == histo ) { return s_bad ; }
00603
00604 const double N = histo->allEntries () ;
00605 if ( 0 >= N ) { return s_bad ; }
00606 const long n = nEntries ( histo , imin , imax ) ;
00607 if ( 0 > n ) { return s_bad ; }
00608 if ( n > N ) { return s_bad ; }
00609
00610 const double _n1 = std::max ( (double) n , 1.0 ) ;
00611 const double _n2 = std::max ( ( N - n ) , 1.0 ) ;
00612
00613 return std::sqrt ( _n1 * _n2 / N ) / N ;
00614 }
00615
00616
00617