00001 #include "AIDA_Cloud2D.h" 00002 #include "AIDA_Histogram2D.h" 00003 #include "AIDA/IAnnotation.h" 00004 #include "AIDA/IAxis.h" 00005 #include <cmath> 00006 #include <set> 00007 #include "AnnotationNumberFormater.h" 00008 #include "EdgeCalculator.h" 00009 00010 static const std::string meanXKey = "MeanX"; 00011 static const std::string rmsXKey = "RmsX"; 00012 static const std::string meanYKey = "MeanY"; 00013 static const std::string rmsYKey = "RmsY"; 00014 static const std::string emptyString = ""; 00015 00016 00017 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::AIDA_Cloud2D( const std::string& title ): 00018 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( title, "ICloud2D", 2 ), 00019 m_cacheSize( Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::defaultCacheSize ), 00020 m_elements(), 00021 m_sumOfWeights( 0 ), 00022 m_sumOfWeightTimesValueX( 0 ), 00023 m_sumOfWeightTimesValueY( 0 ), 00024 m_sumOfWeightTimesSquaredValueX( 0 ), 00025 m_sumOfWeightTimesSquaredValueY( 0 ), 00026 m_lowEdgeX( 0 ), 00027 m_lowEdgeY( 0 ), 00028 m_highEdgeX( 0 ), 00029 m_highEdgeY( 0 ), 00030 m_histo( 0 ) 00031 { 00032 setCacheSize( m_cacheSize ); 00033 00035 AIDA::IAnnotation& annotation = annotationNoUpdate(); 00036 annotation.addItem( meanXKey, emptyString, false ); 00037 annotation.addItem( rmsXKey, emptyString, false ); 00038 annotation.addItem( meanYKey, emptyString, false ); 00039 annotation.addItem( rmsYKey, emptyString, false ); 00040 } 00041 00042 00043 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::AIDA_Cloud2D( const AIDA_Cloud2D& h ): 00044 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( h.title(), "ICloud2D", 2 ), 00045 m_cacheSize( h.m_cacheSize ), 00046 m_elements( h.m_elements ), 00047 m_sumOfWeights( h.m_sumOfWeights ), 00048 m_sumOfWeightTimesValueX( h.m_sumOfWeightTimesValueX ), 00049 m_sumOfWeightTimesValueY( h.m_sumOfWeightTimesValueY ), 00050 m_sumOfWeightTimesSquaredValueX( h.m_sumOfWeightTimesSquaredValueX ), 00051 m_sumOfWeightTimesSquaredValueY( h.m_sumOfWeightTimesSquaredValueY ), 00052 m_lowEdgeX( h.m_lowEdgeX ), 00053 m_lowEdgeY( h.m_lowEdgeY ), 00054 m_highEdgeX( h.m_highEdgeX ), 00055 m_highEdgeY( h.m_highEdgeY ), 00056 m_histo( 0 ) 00057 { 00058 if ( h.m_histo ) { 00059 m_histo = new Anaphe::AIDA_Histogram_native::AIDA_Histogram2D( * ( dynamic_cast<const Anaphe::AIDA_Histogram_native::AIDA_Histogram2D*>( h.m_histo ) ) ); 00060 } 00061 00063 AIDA::IAnnotation& annotation = annotationNoUpdate(); 00064 std::set< std::string > existingAnnotationItems; 00065 for ( int item = 0; item < annotation.size(); ++item ) { 00066 existingAnnotationItems.insert( annotation.key( item ) ); 00067 } 00068 const AIDA::IAnnotation& otherAnnotation = h.annotation(); 00069 for ( int itemNew = 0; itemNew < otherAnnotation.size(); ++itemNew ) { 00070 const std::string& key = otherAnnotation.key( itemNew ); 00071 if ( existingAnnotationItems.find( key ) == existingAnnotationItems.end() ) { 00072 annotation.addItem( key, otherAnnotation.value( itemNew ), false ); 00073 } 00074 } 00075 } 00076 00077 00078 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::AIDA_Cloud2D( const AIDA::ICloud2D& h ): 00079 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( h.title(), "ICloud2D", 2 ), 00080 m_cacheSize( Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::defaultCacheSize ), 00081 m_elements(), 00082 m_sumOfWeights( 0 ), 00083 m_sumOfWeightTimesValueX( 0 ), 00084 m_sumOfWeightTimesValueY( 0 ), 00085 m_sumOfWeightTimesSquaredValueX( 0 ), 00086 m_sumOfWeightTimesSquaredValueY( 0 ), 00087 m_lowEdgeX( 0 ), 00088 m_lowEdgeY( 0 ), 00089 m_highEdgeX( 0 ), 00090 m_highEdgeY( 0 ), 00091 m_histo( 0 ) 00092 { 00093 if ( h.isConverted() ) { 00094 AIDA::ICloud2D& c = const_cast<AIDA::ICloud2D&>( h ); 00095 const AIDA::IHistogram2D& histo = c.histogram(); 00096 m_histo = new Anaphe::AIDA_Histogram_native::AIDA_Histogram2D( histo ); 00097 } 00098 else { 00099 setCacheSize( m_cacheSize ); 00100 for ( int i = 0; i < h.entries(); ++i ) this->fill( h.valueX( i ), h.valueY( i ), h.weight( i ) ); 00101 } 00102 00104 AIDA::IAnnotation& annotation = annotationNoUpdate(); 00105 std::set< std::string > existingAnnotationItems; 00106 for ( int item = 0; item < annotation.size(); ++item ) { 00107 existingAnnotationItems.insert( annotation.key( item ) ); 00108 } 00109 const AIDA::IAnnotation& otherAnnotation = h.annotation(); 00110 for ( int itemNew = 0; itemNew < otherAnnotation.size(); ++itemNew ) { 00111 const std::string& key = otherAnnotation.key( itemNew ); 00112 if ( existingAnnotationItems.find( key ) == existingAnnotationItems.end() ) { 00113 annotation.addItem( key, otherAnnotation.value( itemNew ), false ); 00114 } 00115 } 00116 } 00117 00118 00119 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::~AIDA_Cloud2D() 00120 { 00121 if ( m_histo ) delete m_histo; 00122 } 00123 00124 00125 void 00126 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::updateAnnotation() const 00127 { 00128 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram::updateAnnotation(); 00129 const AIDA::IAnnotation& anno = annotationNoUpdate(); 00130 AIDA::IAnnotation& annotation = const_cast< AIDA::IAnnotation& >( anno ); 00131 00132 annotation.setValue( meanXKey, anaphe_annotationNumberFormater.formatDouble( meanX() ) ); 00133 annotation.setValue( rmsXKey, anaphe_annotationNumberFormater.formatDouble( rmsX() ) ); 00134 annotation.setValue( meanYKey, anaphe_annotationNumberFormater.formatDouble( meanY() ) ); 00135 annotation.setValue( rmsYKey, anaphe_annotationNumberFormater.formatDouble( rmsY() ) ); 00136 } 00137 00138 00139 bool 00140 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::reset() 00141 { 00142 if ( m_histo ) { 00143 delete m_histo; 00144 m_histo = 0; 00145 } 00146 m_elements.clear(); 00147 setCacheSize( m_cacheSize ); 00148 m_sumOfWeights = 0; 00149 m_sumOfWeightTimesValueX = m_sumOfWeightTimesValueY = 0; 00150 m_sumOfWeightTimesSquaredValueX = m_sumOfWeightTimesSquaredValueY = 0; 00151 m_lowEdgeX = m_lowEdgeY = 0; 00152 m_highEdgeX = m_highEdgeY = 0; 00153 return true; 00154 } 00155 00156 00157 int 00158 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::entries() const 00159 { 00160 if ( m_histo ) { 00161 return m_histo->entries(); 00162 } 00163 else { 00164 return m_elements.size(); 00165 } 00166 } 00167 00168 00169 double 00170 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::sumOfWeights() const 00171 { 00172 if ( m_histo ) { 00173 return m_histo->sumBinHeights(); 00174 } 00175 else { 00176 return m_sumOfWeights; 00177 } 00178 } 00179 00180 00181 bool 00182 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::convertToHistogram() 00183 { 00184 if ( m_histo || m_elements.size() < 2 ) return false; 00185 double lowEdgeX, highEdgeX; 00186 edgeCalculator.calculateEdges( m_lowEdgeX, m_highEdgeX, Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::defaultNumberOfBins, lowEdgeX, highEdgeX ); 00187 double lowEdgeY, highEdgeY; 00188 edgeCalculator.calculateEdges( m_lowEdgeY, m_highEdgeY, Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::defaultNumberOfBins, lowEdgeY, highEdgeY ); 00189 Anaphe::AIDA_Histogram_native::AIDA_Histogram2D* p = 00190 new Anaphe::AIDA_Histogram_native::AIDA_Histogram2D( title() + " (supporting histogram)", 00191 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::defaultNumberOfBins, 00192 lowEdgeX, highEdgeX, 00193 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::defaultNumberOfBins, 00194 lowEdgeY, highEdgeY ); 00195 p->setName( name() + "_supportingHistogram" ); 00196 m_histo = p; 00197 for ( unsigned int i = 0; i < m_elements.size(); ++i ) m_histo->fill( m_elements[i].x, m_elements[i].y, m_elements[i].w ); 00198 m_elements.clear(); 00199 return true; 00200 } 00201 00202 00203 bool 00204 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::isConverted() const 00205 { 00206 return ( m_histo != 0 ); 00207 } 00208 00209 00210 bool 00211 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::scale( double scaleFactor ) 00212 { 00213 if ( m_histo ) return m_histo->scale( scaleFactor ); 00214 else { 00215 for ( unsigned int i = 0; i < m_elements.size(); ++i ) { 00216 m_elements[i].w *= scaleFactor; 00217 } 00218 m_sumOfWeights *= scaleFactor; 00219 m_sumOfWeightTimesValueX *= scaleFactor; 00220 m_sumOfWeightTimesValueY *= scaleFactor; 00221 m_sumOfWeightTimesSquaredValueX *= scaleFactor; 00222 m_sumOfWeightTimesSquaredValueY *= scaleFactor; 00223 return true; 00224 } 00225 } 00226 00227 00228 bool 00229 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::fill( double x, double y, double weight ) 00230 { 00231 if ( m_histo ) return m_histo->fill( x, y, weight ); 00232 else { 00233 if ( m_elements.empty() ) { 00234 m_lowEdgeX = m_highEdgeX = x; 00235 m_lowEdgeY = m_highEdgeY = y; 00236 } 00237 else { 00238 if ( m_lowEdgeX > x ) m_lowEdgeX = x; 00239 if ( m_highEdgeX < x ) m_highEdgeX = x; 00240 if ( m_lowEdgeY > y ) m_lowEdgeY = y; 00241 if ( m_highEdgeY < y ) m_highEdgeY = y; 00242 } 00243 m_elements.push_back( Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::Cloud2DElement( x, y, weight ) ); 00244 m_sumOfWeights += weight; 00245 m_sumOfWeightTimesValueX += weight * x; 00246 m_sumOfWeightTimesValueY += weight * y; 00247 m_sumOfWeightTimesSquaredValueX += weight * x * x; 00248 m_sumOfWeightTimesSquaredValueY += weight * y * y; 00249 if ( m_elements.size() >= m_cacheSize ) convertToHistogram(); 00250 return true; 00251 } 00252 } 00253 00254 00255 double 00256 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::lowerEdgeX() const 00257 { 00258 if ( m_histo ) return m_histo->xAxis().lowerEdge(); 00259 else return m_lowEdgeX; 00260 } 00261 00262 00263 double 00264 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::lowerEdgeY() const 00265 { 00266 if ( m_histo ) return m_histo->yAxis().lowerEdge(); 00267 else return m_lowEdgeY; 00268 } 00269 00270 00271 double 00272 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::upperEdgeX() const 00273 { 00274 if ( m_histo ) return m_histo->xAxis().upperEdge(); 00275 else return m_highEdgeX; 00276 } 00277 00278 00279 double 00280 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::upperEdgeY() const 00281 { 00282 if ( m_histo ) return m_histo->yAxis().upperEdge(); 00283 else return m_highEdgeY; 00284 } 00285 00286 00287 double 00288 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::valueX( int index ) const 00289 { 00290 if ( m_histo || index < 0 ) return 0; 00291 if ( static_cast< unsigned int >( index ) >= m_elements.size() ) return 0; 00292 return m_elements[index].x; 00293 } 00294 00295 00296 double 00297 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::valueY( int index ) const 00298 { 00299 if ( m_histo || index < 0 ) return 0; 00300 if ( static_cast< unsigned int >( index ) >= m_elements.size() ) return 0; 00301 return m_elements[index].y; 00302 } 00303 00304 00305 double 00306 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::weight( int index ) const 00307 { 00308 if ( m_histo || index < 0 ) return 0; 00309 if ( static_cast< unsigned int >( index ) >= m_elements.size() ) return 0; 00310 return m_elements[index].w; 00311 } 00312 00313 00314 double 00315 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::meanX() const 00316 { 00317 if ( m_histo ) return m_histo->meanX(); 00318 else if ( m_sumOfWeights ) { 00319 return ( m_sumOfWeightTimesValueX / m_sumOfWeights ); 00320 } 00321 else return 0; 00322 } 00323 00324 00325 double 00326 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::meanY() const 00327 { 00328 if ( m_histo ) return m_histo->meanY(); 00329 else if ( m_sumOfWeights ) { 00330 return ( m_sumOfWeightTimesValueY / m_sumOfWeights ); 00331 } 00332 else return 0; 00333 } 00334 00335 00336 double 00337 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::rmsX() const 00338 { 00339 if ( m_histo ) return m_histo->rmsX(); 00340 else if ( m_sumOfWeights ) { 00341 return std::sqrt(std::abs( m_sumOfWeightTimesSquaredValueX * m_sumOfWeights - m_sumOfWeightTimesValueX*m_sumOfWeightTimesValueX))/std::abs(m_sumOfWeights); 00342 } 00343 else return 0; 00344 } 00345 00346 00347 double 00348 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::rmsY() const 00349 { 00350 if ( m_histo ) return m_histo->rmsY(); 00351 else if ( m_sumOfWeights ) { 00352 return std::sqrt(std::abs( m_sumOfWeightTimesSquaredValueY * m_sumOfWeights - m_sumOfWeightTimesValueY*m_sumOfWeightTimesValueY))/std::abs(m_sumOfWeights); 00353 } 00354 else return 0; 00355 } 00356 00357 00358 bool 00359 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::convert( int nBinsX, double lowerEdgeX, double upperEdgeX, 00360 int nBinsY, double lowerEdgeY, double upperEdgeY ) 00361 { 00362 if ( m_histo ) return false; 00363 Anaphe::AIDA_Histogram_native::AIDA_Histogram2D* p = new Anaphe::AIDA_Histogram_native::AIDA_Histogram2D( title() + " (supporting histogram)", 00364 nBinsX, lowerEdgeX, upperEdgeX, 00365 nBinsY, lowerEdgeY, upperEdgeY ); 00366 p->setName( name() + "_supportingHistogram" ); 00367 m_histo = p; 00368 for ( unsigned int i = 0; i < m_elements.size(); ++i ) m_histo->fill( m_elements[i].x, m_elements[i].y, m_elements[i].w ); 00369 m_elements.clear(); 00370 return true; 00371 } 00372 00373 00374 bool 00375 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::convert( const std::vector< double >& binEdgeX, const std::vector< double >& binEdgeY ) 00376 { 00377 if ( m_histo ) return false; 00378 Anaphe::AIDA_Histogram_native::AIDA_Histogram2D* p = new Anaphe::AIDA_Histogram_native::AIDA_Histogram2D( title() + " (supporting histogram)", binEdgeX, binEdgeY ); 00379 p->setName( name() + "_supportingHistogram" ); 00380 m_histo = p; 00381 for ( unsigned int i = 0; i < m_elements.size(); ++i ) m_histo->fill( m_elements[i].x, m_elements[i].y, m_elements[i].w ); 00382 m_elements.clear(); 00383 return true; 00384 } 00385 00386 00387 bool 00388 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::fillHistogram( AIDA::IHistogram2D& hist ) const 00389 { 00390 if ( m_histo ) { 00391 AIDA::IHistogram2D& h = *m_histo; 00392 for ( int ib = -2; ib < h.yAxis().bins(); ++ib ) { 00393 int i = ib; 00394 if ( ib == -2 ) i = static_cast<int>( AIDA::IAxis::OVERFLOW_BIN ); 00395 else if ( ib == -1 ) i = static_cast<int>( AIDA::IAxis::UNDERFLOW_BIN ); 00396 00397 for ( int jb = -2; jb < h.yAxis().bins(); ++jb ) { 00398 int j = ib; 00399 if ( jb == -2 ) j = static_cast<int>( AIDA::IAxis::OVERFLOW_BIN ); 00400 else if ( jb == -1 ) j = static_cast<int>( AIDA::IAxis::UNDERFLOW_BIN ); 00401 00402 const int entries = h.binEntries( i, j ); 00403 if ( entries == 0 ) continue; 00404 const double newCentreX = h.binMeanX( i, j ); 00405 const double newCentreY = h.binMeanY( i, j ); 00406 const double newValue = h.binHeight( i, j ); 00407 if ( entries == 1 ) hist.fill( newCentreX, newCentreY, newValue ); 00408 else { 00409 double newError = h.binError( i, j ); 00410 const double w1 = 00411 ( 2 * newValue - std::sqrt( ( 4 * entries * newError * newError - newValue * newValue ) / ( entries - 1 ) ) ) / ( 2 * entries ); 00412 const double w2 = newValue - ( entries - 1 ) * w1; 00413 for ( int ie = 0; ie < entries - 1; ++ie ) { 00414 hist.fill( newCentreX, newCentreY, w1 ); 00415 } 00416 hist.fill( newCentreX, newCentreY, w2 ); 00417 } 00418 } 00419 } 00420 } 00421 else { 00422 for ( std::vector< Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::Cloud2DElement >::const_iterator iElement = m_elements.begin(); 00423 iElement != m_elements.end(); ++iElement ) { 00424 hist.fill( iElement->x, iElement->y, iElement->w ); 00425 } 00426 } 00427 return true; 00428 } 00429 00430 00431 const AIDA::IHistogram2D& 00432 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::histogram() const 00433 { 00434 if ( ! m_histo ) const_cast<Anaphe::AIDA_Histogram_native::AIDA_Cloud2D*>(this)->convertToHistogram(); 00435 return *m_histo; 00436 } 00437 00438 00439 bool 00440 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::setCacheSize( unsigned int newCacheSize ) 00441 { 00442 m_cacheSize = newCacheSize; 00443 if ( m_cacheSize != static_cast<unsigned int>( -1 ) ) m_elements.reserve( newCacheSize ); 00444 return true; 00445 } 00446 00447 00448 unsigned int 00449 Anaphe::AIDA_Histogram_native::AIDA_Cloud2D::cacheSize() const 00450 { 00451 return m_cacheSize; 00452 }