00001 #include "AIDA_Histogram1D.h"
00002 #include "EvenBinAxis.h"
00003 #include "VariableBinAxis.h"
00004 #include "GravityBin1D.h"
00005 #include "AIDA/IAnnotation.h"
00006 #include <typeinfo>
00007 #include <cmath>
00008 #include <set>
00009 #include "AnnotationNumberFormater.h"
00010
00011 static const unsigned int numberOfExtraBins = 2;
00012 static const std::string meanKey = "Mean";
00013 static const std::string rmsKey = "Rms";
00014 static const std::string extra_entriesKey = "Extra Entries";
00015 static const std::string overflowKey = "Overflow";
00016 static const std::string underflowKey = "Underflow";
00017 static const std::string emptyString = "";
00018
00019 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::AIDA_Histogram1D( const std::string& title,
00020 int numberOfBins,
00021 double lowEdge,
00022 double highEdge ):
00023 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( title, "IHistogram1D", 1 ),
00024 m_axis( new EvenBinAxis( std::abs( numberOfBins ), lowEdge, highEdge ) ),
00025 m_bins( std::abs( numberOfBins ) + numberOfExtraBins ),
00026 m_validStatistics( false )
00027 {
00028 m_sumWeightTimesSquaredX = 0;
00029 for ( unsigned int i = 0; i < m_bins.size(); ++i ) m_bins[ i ] = new Anaphe::AIDA_Histogram_native::GravityBin1D;
00030
00032 AIDA::IAnnotation& annotation = annotationNoUpdate();
00033 annotation.addItem( meanKey, emptyString, false );
00034 annotation.addItem( rmsKey, emptyString, false );
00035 annotation.addItem( extra_entriesKey, emptyString, false );
00036 annotation.addItem( overflowKey, emptyString, false );
00037 annotation.addItem( underflowKey, emptyString, false );
00038 }
00039
00040
00041 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::AIDA_Histogram1D( const std::string& title,
00042 const std::vector< double >& edges ):
00043 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( title, "IHistogram1D", 1 ),
00044 m_axis( new VariableBinAxis( edges ) ),
00045 m_bins( edges.size() - 1 + numberOfExtraBins ),
00046 m_validStatistics( false )
00047 {
00048 m_sumWeightTimesSquaredX = 0;
00049 for ( unsigned int i = 0; i < m_bins.size(); ++i ) m_bins[ i ] = new Anaphe::AIDA_Histogram_native::GravityBin1D;
00050
00052 AIDA::IAnnotation& annotation = annotationNoUpdate();
00053 annotation.addItem( meanKey, emptyString, false );
00054 annotation.addItem( rmsKey, emptyString, false );
00055 annotation.addItem( extra_entriesKey, emptyString, false );
00056 annotation.addItem( overflowKey, emptyString, false );
00057 annotation.addItem( underflowKey, emptyString, false );
00058 }
00059
00060
00061 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::AIDA_Histogram1D( const Anaphe::AIDA_Histogram_native::AIDA_Histogram1D& h ):
00062 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( h.title(), "IHistogram1D", 1 ),
00063 m_axis( 0 ),
00064 m_bins( h.m_bins.size() ),
00065 m_validStatistics( false )
00066 {
00067 m_sumWeightTimesSquaredX = 0;
00068
00069
00070 const AIDA::IAxis& otherAxis = h.axis();
00071 if ( otherAxis.isFixedBinning() ) {
00072 m_axis = new EvenBinAxis( otherAxis.bins(),
00073 otherAxis.lowerEdge(),
00074 otherAxis.upperEdge() );
00075 }
00076 else {
00077 std::vector< double > edges( otherAxis.bins() + 1);
00078 for ( int i = 0; i < otherAxis.bins(); ++i ) edges[i] = otherAxis.binLowerEdge( i );
00079 edges.back() = otherAxis.upperEdge();
00080 m_axis = new VariableBinAxis( edges );
00081 }
00082
00083
00084 for ( unsigned int i = 0; i < m_bins.size(); ++i ) m_bins[i] = new GravityBin1D( *( h.m_bins[i] ) );
00085 setRms( h.rms() );
00086
00088 AIDA::IAnnotation& annotation = annotationNoUpdate();
00089 std::set< std::string > existingAnnotationItems;
00090 for ( int item = 0; item < annotation.size(); ++item ) {
00091 existingAnnotationItems.insert( annotation.key( item ) );
00092 }
00093 const AIDA::IAnnotation& otherAnnotation = h.annotation();
00094 for ( int itemNew = 0; itemNew < otherAnnotation.size(); ++itemNew ) {
00095 const std::string& key = otherAnnotation.key( itemNew );
00096 if ( existingAnnotationItems.find( key ) == existingAnnotationItems.end() ) {
00097 annotation.addItem( key, otherAnnotation.value( itemNew ), false );
00098 }
00099 }
00100 }
00101
00102
00103 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::AIDA_Histogram1D( const AIDA::IHistogram1D& h ):
00104 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( h.title(), "IHistogram1D", 1 ),
00105 m_axis( 0 ),
00106 m_bins( h.axis().bins() + numberOfExtraBins ),
00107 m_validStatistics( false )
00108 {
00109 m_sumWeightTimesSquaredX = 0;
00110
00111
00112 const AIDA::IAxis& otherAxis = h.axis();
00113 if ( h.axis().isFixedBinning() ) {
00114 m_axis = new EvenBinAxis( otherAxis.bins(),
00115 otherAxis.lowerEdge(),
00116 otherAxis.upperEdge() );
00117 }
00118 else {
00119 std::vector< double > edges( otherAxis.bins() + 1);
00120 for ( int i = 0; i < otherAxis.bins(); ++i ) edges[i] = otherAxis.binLowerEdge( i );
00121 edges.back() = otherAxis.upperEdge();
00122 m_axis = new VariableBinAxis( edges );
00123 }
00124
00125
00126 for ( unsigned int i = 0; i < m_bins.size(); ++i ) m_bins[i] = new GravityBin1D;
00127
00128
00129 for ( unsigned int iBin = numberOfExtraBins; iBin < m_bins.size(); ++iBin ) {
00130 m_bins[iBin]->set( h.binEntries( iBin - numberOfExtraBins ),
00131 h.binHeight( iBin - numberOfExtraBins ),
00132 h.binError( iBin - numberOfExtraBins ),
00133 h.binMean( iBin - numberOfExtraBins ) );
00134 }
00135
00136
00137 const int underFlowBin = static_cast< int >( AIDA::IAxis::UNDERFLOW_BIN );
00138 m_bins[ underFlowBin ]->set( h.binEntries( underFlowBin ),
00139 h.binHeight( underFlowBin ),
00140 h.binError( underFlowBin ),
00141 h.binMean( underFlowBin ) );
00142
00143 const int overFlowBin = static_cast< int >( AIDA::IAxis::OVERFLOW_BIN );
00144 m_bins[ underFlowBin ]->set( h.binEntries( overFlowBin ),
00145 h.binHeight( overFlowBin ),
00146 h.binError( overFlowBin ),
00147 h.binMean( overFlowBin ) );
00148 setRms( h.rms() );
00149
00151 AIDA::IAnnotation& annotation = annotationNoUpdate();
00152 std::set< std::string > existingAnnotationItems;
00153 for ( int item = 0; item < annotation.size(); ++item ) {
00154 existingAnnotationItems.insert( annotation.key( item ) );
00155 }
00156 const AIDA::IAnnotation& otherAnnotation = h.annotation();
00157 for ( int itemNew = 0; itemNew < otherAnnotation.size(); ++itemNew ) {
00158 const std::string& key = otherAnnotation.key( itemNew );
00159 if ( existingAnnotationItems.find( key ) == existingAnnotationItems.end() ) {
00160 annotation.addItem( key, otherAnnotation.value( itemNew ), false );
00161 }
00162 }
00163 }
00164
00165
00166 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::~AIDA_Histogram1D()
00167 {
00168 if ( m_axis ) delete m_axis;
00169 for ( unsigned int i = 0; i < m_bins.size(); ++i ) {
00170 if ( m_bins[ i ] ) delete m_bins[ i ];
00171 }
00172 }
00173
00174
00175 bool
00176 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::reset()
00177 {
00178 for ( unsigned int i = 0; i < m_bins.size(); ++i ) m_bins[ i ]->reset();
00179 m_sumWeightTimesSquaredX = 0;
00180 m_validStatistics = false;
00181 setUpToDate( false );
00182 return true;
00183 }
00184
00185
00186 int
00187 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::entries() const
00188 {
00189 calculateStatistics();
00190 return m_entries;
00191 }
00192
00193
00194 int
00195 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::allEntries() const
00196 {
00197 return ( entries() + extraEntries() );
00198 }
00199
00200
00201 int
00202 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::extraEntries() const
00203 {
00204 calculateStatistics();
00205 return m_extraEntries;
00206 }
00207
00208
00209 void
00210 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::updateAnnotation() const
00211 {
00212 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram::updateAnnotation();
00213 const AIDA::IAnnotation& anno = annotationNoUpdate();
00214 AIDA::IAnnotation& annotation = const_cast< AIDA::IAnnotation& >( anno );
00215
00216 annotation.setValue( meanKey, anaphe_annotationNumberFormater.formatDouble( mean() ) );
00217 annotation.setValue( rmsKey, anaphe_annotationNumberFormater.formatDouble( rms() ) );
00218 annotation.setValue( extra_entriesKey, anaphe_annotationNumberFormater.formatInteger( extraEntries() ) );
00219 annotation.setValue( underflowKey, anaphe_annotationNumberFormater.formatInteger( m_bins[numberOfExtraBins + AIDA::IAxis::UNDERFLOW_BIN]->entries() ) );
00220 annotation.setValue( overflowKey, anaphe_annotationNumberFormater.formatInteger( m_bins[numberOfExtraBins + AIDA::IAxis::OVERFLOW_BIN]->entries() ) );
00221 }
00222
00223
00224 double
00225 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::equivalentBinEntries() const
00226 {
00227 calculateStatistics();
00228 return m_ebe;
00229 }
00230
00231
00232 double
00233 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::sumBinHeights() const
00234 {
00235 calculateStatistics();
00236 return m_sumBinHeights;
00237 }
00238
00239
00240 double
00241 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::sumExtraBinHeights() const
00242 {
00243 calculateStatistics();
00244 return m_sumExtraBinHeights;
00245 }
00246
00247
00248 double
00249 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::sumAllBinHeights() const
00250 {
00251 return ( sumBinHeights() + sumExtraBinHeights() );
00252 }
00253
00254
00255 double
00256 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::minBinHeight() const
00257 {
00258 calculateStatistics();
00259 return m_minHeight;
00260 }
00261
00262
00263 double
00264 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::maxBinHeight() const
00265 {
00266 calculateStatistics();
00267 return m_maxHeight;
00268 }
00269
00270
00271 bool
00272 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::scale( double scaleFactor )
00273 {
00274 for ( unsigned int i = 0; i < m_bins.size(); ++i ) m_bins[ i ]->scale( scaleFactor );
00275 m_sumWeightTimesSquaredX *= scaleFactor;
00276 setUpToDate( false );
00277 m_validStatistics = false;
00278 return true;
00279 }
00280
00281
00282 bool
00283 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::fill( double x, double weight )
00284 {
00285 const int binIndex = m_axis->coordToIndex( x );
00286 m_bins[binIndex + numberOfExtraBins]->fill( weight, x );
00287 if ( binIndex >= 0 ) m_sumWeightTimesSquaredX += weight * x * x;
00288 setUpToDate( false );
00289 m_validStatistics = false;
00290 return true;
00291 }
00292
00293
00294 double
00295 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::binMean( int index ) const
00296 {
00297 unsigned int realIndex = index + numberOfExtraBins;
00298 if ( realIndex < 0 || realIndex>= m_bins.size() ) return 0;
00299 const Anaphe::AIDA_Histogram_native::GravityBin1D& bin = * ( m_bins[ realIndex ] );
00300 if ( bin.entries() == 0 ) {
00301 return m_axis->binLowerEdge( index ) + 0.5 * m_axis->binWidth( index );
00302 }
00303 else return bin.centreOfGravityX();
00304 }
00305
00306
00307 int
00308 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::binEntries( int index ) const
00309 {
00310 unsigned int realIndex = index + numberOfExtraBins;
00311 if ( realIndex < 0 || realIndex>= m_bins.size() ) return 0;
00312 return m_bins[ realIndex ]->entries();
00313 }
00314
00315
00316 double
00317 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::binHeight( int index ) const
00318 {
00319 unsigned int realIndex = index + numberOfExtraBins;
00320 if ( realIndex < 0 || realIndex>= m_bins.size() ) return 0;
00321 return m_bins[ realIndex ]->height();
00322 }
00323
00324
00325 double
00326 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::binError( int index ) const
00327 {
00328 unsigned int realIndex = index + numberOfExtraBins;
00329 if ( realIndex < 0 || realIndex>= m_bins.size() ) return 0;
00330 return m_bins[ realIndex ]->error();
00331 }
00332
00333
00334 double
00335 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::mean() const
00336 {
00337 calculateStatistics();
00338 return m_mean;
00339 }
00340
00341
00342 double
00343 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::rms() const
00344 {
00345 calculateStatistics();
00346 return m_rms;
00347 }
00348
00349
00350 bool
00351 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::calculateStatistics() const
00352 {
00353 if ( m_validStatistics ) return true;
00354
00355
00356 m_sumBinHeights = 0;
00357 double sww = 0;
00358 double swp = 0;
00359 m_entries = 0;
00360 m_maxHeight = m_minHeight = m_bins[ numberOfExtraBins ]->height();
00361 for ( unsigned int i = numberOfExtraBins; i < m_bins.size(); ++i ) {
00362 const GravityBin1D& bin = *( m_bins[ i ] );
00363 const double binMean = bin.centreOfGravityX();
00364 const double binHeight = bin.height();
00365 const double binErrorSquared = bin.errorSquared();
00366 m_entries += bin.entries();
00367 m_sumBinHeights += binHeight;
00368 sww += binErrorSquared;
00369 swp += binMean * binHeight;
00370 if ( m_maxHeight < binHeight ) m_maxHeight = binHeight;
00371 if ( m_minHeight > binHeight ) m_minHeight = binHeight;
00372 }
00373
00374 if ( m_sumBinHeights == 0 ) {
00375 m_mean = m_rms = 0;
00376 }
00377 else {
00378 m_mean = swp / m_sumBinHeights;
00379 m_rms = std::sqrt( std::abs( m_sumWeightTimesSquaredX / m_sumBinHeights - m_mean * m_mean ) );
00380 }
00381
00382 if ( sww ) {
00383 m_ebe = m_sumBinHeights * m_sumBinHeights / sww;
00384 }
00385 else {
00386 m_ebe = 0;
00387 }
00388
00389
00390 m_sumExtraBinHeights = 0;
00391 m_extraEntries = 0;
00392 for ( unsigned int i = 0; i < numberOfExtraBins; ++i ) {
00393 const GravityBin1D& bin = *( m_bins[ i ] );
00394 m_extraEntries += bin.entries();
00395 m_sumExtraBinHeights += bin.height();
00396 }
00397
00398
00399 m_validStatistics = true;
00400 return m_validStatistics;
00401 }
00402
00403
00404 const AIDA::IAxis&
00405 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::axis() const
00406 {
00407 return *m_axis;
00408 }
00409
00410
00411 int
00412 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::coordToIndex( double coord ) const
00413 {
00414 return m_axis->coordToIndex( coord );
00415 }
00416
00417
00418 bool
00419 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::add( const AIDA::IHistogram1D & h )
00420 {
00421
00422 const AIDA::IAxis& otherAxis = h.axis();
00423 const AIDA::IAxis& myAxis = *m_axis;
00424 if ( otherAxis.bins() != myAxis.bins() ) return false;
00425 for ( int iBin = 0; iBin < myAxis.bins(); ++iBin ) {
00426 const double otherLowEdge = otherAxis.binLowerEdge( iBin );
00427 const double myLowEdge = myAxis.binLowerEdge( iBin );
00428 if ( otherLowEdge != myLowEdge ) return false;
00429 }
00430 if ( otherAxis.upperEdge() != myAxis.upperEdge() ) return false;
00431
00432
00433
00434 try {
00435 const Anaphe::AIDA_Histogram_native::AIDA_Histogram1D& other = dynamic_cast<const Anaphe::AIDA_Histogram_native::AIDA_Histogram1D&>( h );
00436 return increment( other );
00437 }
00438 catch( std::bad_cast ) {
00439 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D * transformed = new Anaphe::AIDA_Histogram_native::AIDA_Histogram1D( h );
00440 bool ret = increment( *transformed );
00441 delete transformed;
00442 return ret;
00443 }
00444 }
00445
00446
00447 bool
00448 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::increment( const AIDA_Histogram1D& h )
00449 {
00450 for ( unsigned int i = 0; i < m_bins.size(); ++i ) {
00451 m_bins[ i ]->increment( *( h.m_bins[i] ) );
00452 }
00453 m_sumWeightTimesSquaredX += h.m_sumWeightTimesSquaredX;
00454 setUpToDate( false );
00455 m_validStatistics = false;
00456 return true;
00457 }
00458
00459
00460 bool
00461 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::setBinContents( int binIndex,
00462 int entries,
00463 double height,
00464 double error,
00465 double centre )
00466 {
00467 unsigned int realIndex = binIndex + numberOfExtraBins;
00468 if ( realIndex < 0 || realIndex>= m_bins.size() ) return false;
00469 setUpToDate( false );
00470 m_validStatistics = false;
00471 return m_bins[ realIndex ]->set( entries, height, error, centre );
00472 }
00473
00474
00475 bool
00476 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D::setRms( double rms )
00477 {
00478 const double mn = mean();
00479 m_sumWeightTimesSquaredX = ( mn*mn + rms*rms) * sumBinHeights();
00480 m_validStatistics = false;
00481 return true;
00482 }