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