00001 #include "AIDA_Cloud1D.h" 00002 #include "AIDA_Histogram1D.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 meanKey = "Mean"; 00011 static const std::string rmsKey = "Rms"; 00012 static const std::string emptyString = ""; 00013 00014 00015 00016 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::AIDA_Cloud1D( const std::string& title ): 00017 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( title, "ICloud1D", 1 ), 00018 m_cacheSize( Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::defaultCacheSize ), 00019 m_elements(), 00020 m_sumOfWeights( 0 ), 00021 m_sumOfWeightTimesValue( 0 ), 00022 m_sumOfWeightTimesSquaredValue( 0 ), 00023 m_lowEdge( 0 ), 00024 m_highEdge( 0 ), 00025 m_histo( 0 ) 00026 { 00027 setCacheSize( m_cacheSize ); 00028 00030 AIDA::IAnnotation& annotation = annotationNoUpdate(); 00031 annotation.addItem( meanKey, emptyString, false ); 00032 annotation.addItem( rmsKey, emptyString, false ); 00033 } 00034 00035 00036 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::AIDA_Cloud1D( const AIDA_Cloud1D& h ): 00037 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( h.title(), "ICloud1D", 1 ), 00038 m_cacheSize( h.m_cacheSize ), 00039 m_elements( h.m_elements ), 00040 m_sumOfWeights( h.m_sumOfWeights ), 00041 m_sumOfWeightTimesValue( h.m_sumOfWeightTimesValue ), 00042 m_sumOfWeightTimesSquaredValue( h.m_sumOfWeightTimesSquaredValue ), 00043 m_lowEdge( h.m_lowEdge ), 00044 m_highEdge( h.m_highEdge ), 00045 m_histo( 0 ) 00046 { 00047 if ( h.m_histo ) { 00048 m_histo = new Anaphe::AIDA_Histogram_native::AIDA_Histogram1D( * ( dynamic_cast<const Anaphe::AIDA_Histogram_native::AIDA_Histogram1D*>( h.m_histo ) ) ); 00049 } 00050 00052 AIDA::IAnnotation& annotation = annotationNoUpdate(); 00053 std::set< std::string > existingAnnotationItems; 00054 for ( int item = 0; item < annotation.size(); ++item ) { 00055 existingAnnotationItems.insert( annotation.key( item ) ); 00056 } 00057 const AIDA::IAnnotation& otherAnnotation = h.annotation(); 00058 for ( int itemNew = 0; itemNew < otherAnnotation.size(); ++itemNew ) { 00059 const std::string& key = otherAnnotation.key( itemNew ); 00060 if ( existingAnnotationItems.find( key ) == existingAnnotationItems.end() ) { 00061 annotation.addItem( key, otherAnnotation.value( itemNew ), false ); 00062 } 00063 } 00064 } 00065 00066 00067 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::AIDA_Cloud1D( const AIDA::ICloud1D& h ): 00068 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram( h.title(), "ICloud1D", 1 ), 00069 m_cacheSize( Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::defaultCacheSize ), 00070 m_elements(), 00071 m_sumOfWeights( 0 ), 00072 m_sumOfWeightTimesValue( 0 ), 00073 m_sumOfWeightTimesSquaredValue( 0 ), 00074 m_lowEdge( 0 ), 00075 m_highEdge( 0 ), 00076 m_histo( 0 ) 00077 { 00078 if ( h.isConverted() ) { 00079 AIDA::ICloud1D& c = const_cast<AIDA::ICloud1D&>( h ); 00080 const AIDA::IHistogram1D& histo = c.histogram(); 00081 m_histo = new Anaphe::AIDA_Histogram_native::AIDA_Histogram1D( histo ); 00082 } 00083 else { 00084 setCacheSize( m_cacheSize ); 00085 for ( int i = 0; i < h.entries(); ++i ) this->fill( h.value( i ), h.weight( i ) ); 00086 } 00087 00089 AIDA::IAnnotation& annotation = annotationNoUpdate(); 00090 std::set< std::string > existingAnnotationItems; 00091 for ( int item = 0; item < annotation.size(); ++item ) { 00092 existingAnnotationItems.insert( annotation.key( item ) ); 00093 } 00094 const AIDA::IAnnotation& otherAnnotation = h.annotation(); 00095 for ( int itemNew = 0; itemNew < otherAnnotation.size(); ++itemNew ) { 00096 const std::string& key = otherAnnotation.key( itemNew ); 00097 if ( existingAnnotationItems.find( key ) == existingAnnotationItems.end() ) { 00098 annotation.addItem( key, otherAnnotation.value( itemNew ), false ); 00099 } 00100 } 00101 } 00102 00103 00104 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::~AIDA_Cloud1D() 00105 { 00106 if ( m_histo ) delete m_histo; 00107 } 00108 00109 00110 void 00111 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::updateAnnotation() const 00112 { 00113 Anaphe::AIDA_Histogram_native::AIDA_BaseHistogram::updateAnnotation(); 00114 const AIDA::IAnnotation& anno = annotationNoUpdate(); 00115 AIDA::IAnnotation& annotation = const_cast< AIDA::IAnnotation& >( anno ); 00116 00117 annotation.setValue( meanKey, anaphe_annotationNumberFormater.formatDouble( mean() ) ); 00118 annotation.setValue( rmsKey, anaphe_annotationNumberFormater.formatDouble( rms() ) ); 00119 } 00120 00121 00122 bool 00123 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::reset() 00124 { 00125 if ( m_histo ) { 00126 delete m_histo; 00127 m_histo = 0; 00128 } 00129 m_elements.clear(); 00130 setCacheSize( m_cacheSize ); 00131 m_sumOfWeights = m_sumOfWeightTimesValue = m_sumOfWeightTimesSquaredValue = m_lowEdge = m_highEdge = 0; 00132 return true; 00133 } 00134 00135 00136 int 00137 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::entries() const 00138 { 00139 if ( m_histo ) { 00140 return m_histo->entries(); 00141 } 00142 else { 00143 return m_elements.size(); 00144 } 00145 } 00146 00147 00148 double 00149 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::sumOfWeights() const 00150 { 00151 if ( m_histo ) { 00152 return m_histo->sumBinHeights(); 00153 } 00154 else { 00155 return m_sumOfWeights; 00156 } 00157 } 00158 00159 00160 bool 00161 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::convertToHistogram() 00162 { 00163 if ( m_histo || m_elements.size() < 2 ) return false; 00164 double lowEdge, highEdge; 00165 edgeCalculator.calculateEdges( m_lowEdge, m_highEdge, Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::defaultNumberOfBins, lowEdge, highEdge ); 00166 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D* p = 00167 new Anaphe::AIDA_Histogram_native::AIDA_Histogram1D( title() + " (supporting histogram)", 00168 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::defaultNumberOfBins, 00169 lowEdge, highEdge ); 00170 p->setName( name() + "_supportingHistogram" ); 00171 m_histo = p; 00172 for ( unsigned int i = 0; i < m_elements.size(); ++i ) m_histo->fill( m_elements[i].x, m_elements[i].w ); 00173 m_elements.clear(); 00174 return true; 00175 } 00176 00177 00178 bool 00179 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::isConverted() const 00180 { 00181 return ( m_histo != 0 ); 00182 } 00183 00184 00185 bool 00186 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::scale( double scaleFactor ) 00187 { 00188 if ( m_histo ) return m_histo->scale( scaleFactor ); 00189 else { 00190 for ( unsigned int i = 0; i < m_elements.size(); ++i ) { 00191 m_elements[i].w *= scaleFactor; 00192 } 00193 m_sumOfWeights *= scaleFactor; 00194 m_sumOfWeightTimesValue *= scaleFactor; 00195 m_sumOfWeightTimesSquaredValue *= scaleFactor; 00196 return true; 00197 } 00198 } 00199 00200 00201 bool 00202 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::fill( double x, double weight ) 00203 { 00204 if ( m_histo ) return m_histo->fill( x, weight ); 00205 else { 00206 if ( m_elements.empty() ) m_lowEdge = m_highEdge = x; 00207 else { 00208 if ( m_lowEdge > x ) m_lowEdge = x; 00209 if ( m_highEdge < x ) m_highEdge = x; 00210 } 00211 m_elements.push_back( Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::Cloud1DElement( x, weight ) ); 00212 m_sumOfWeights += weight; 00213 m_sumOfWeightTimesValue += weight * x; 00214 m_sumOfWeightTimesSquaredValue += weight * x * x; 00215 if ( m_elements.size() >= m_cacheSize ) convertToHistogram(); 00216 return true; 00217 } 00218 } 00219 00220 00221 double 00222 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::lowerEdge() const 00223 { 00224 if ( m_histo ) return m_histo->axis().lowerEdge(); 00225 else return m_lowEdge; 00226 } 00227 00228 00229 double 00230 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::upperEdge() const 00231 { 00232 if ( m_histo ) return m_histo->axis().upperEdge(); 00233 else return m_highEdge; 00234 } 00235 00236 00237 double 00238 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::value( int index ) const 00239 { 00240 if ( m_histo || index < 0 ) return 0; 00241 if ( static_cast< unsigned int >( index ) >= m_elements.size() ) return 0; 00242 return m_elements[index].x; 00243 } 00244 00245 double 00246 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::weight( int index ) const 00247 { 00248 if ( m_histo || index < 0 ) return 0; 00249 if ( static_cast< unsigned int >( index ) >= m_elements.size() ) return 0; 00250 return m_elements[index].w; 00251 } 00252 00253 00254 double 00255 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::mean() const 00256 { 00257 if ( m_histo ) return m_histo->mean(); 00258 else if ( m_sumOfWeights ) { 00259 return ( m_sumOfWeightTimesValue / m_sumOfWeights ); 00260 } 00261 else return 0; 00262 } 00263 00264 00265 double 00266 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::rms() const 00267 { 00268 if ( m_histo ) return m_histo->rms(); 00269 else if ( m_sumOfWeights ) { 00270 return std::sqrt(std::abs( m_sumOfWeightTimesSquaredValue * m_sumOfWeights - m_sumOfWeightTimesValue*m_sumOfWeightTimesValue))/std::abs(m_sumOfWeights); 00271 } 00272 else return 0; 00273 } 00274 00275 00276 bool 00277 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::convert( int nBins, double lowerEdge, double upperEdge ) 00278 { 00279 if ( m_histo ) return false; 00280 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D* p = new Anaphe::AIDA_Histogram_native::AIDA_Histogram1D( title() + " (supporting histogram)", nBins, lowerEdge, upperEdge ); 00281 p->setName( name() + "_supportingHistogram" ); 00282 m_histo = p; 00283 for ( unsigned int i = 0; i < m_elements.size(); ++i ) m_histo->fill( m_elements[i].x, m_elements[i].w ); 00284 m_elements.clear(); 00285 return true; 00286 } 00287 00288 00289 bool 00290 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::convert( const std::vector< double >& binEdge ) 00291 { 00292 if ( m_histo ) return false; 00293 Anaphe::AIDA_Histogram_native::AIDA_Histogram1D* p = new Anaphe::AIDA_Histogram_native::AIDA_Histogram1D( title() + " (supporting histogram)", binEdge ); 00294 p->setName( name() + "_supportingHistogram" ); 00295 m_histo = p; 00296 for ( unsigned int i = 0; i < m_elements.size(); ++i ) m_histo->fill( m_elements[i].x, m_elements[i].w ); 00297 m_elements.clear(); 00298 return true; 00299 } 00300 00301 00302 const AIDA::IHistogram1D& 00303 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::histogram() const 00304 { 00305 if ( ! m_histo ) const_cast<Anaphe::AIDA_Histogram_native::AIDA_Cloud1D*>(this)->convertToHistogram(); 00306 return *m_histo; 00307 } 00308 00309 00310 bool 00311 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::fillHistogram( AIDA::IHistogram1D& hist ) const 00312 { 00313 if ( m_histo ) { 00314 AIDA::IHistogram1D& h = *m_histo; 00315 for ( int ib = -2; ib < h.axis().bins(); ++ib ) { 00316 int i = ib; 00317 if ( ib == -2 ) i = static_cast<int>( AIDA::IAxis::OVERFLOW_BIN ); 00318 else if ( ib == -1 ) i = static_cast<int>( AIDA::IAxis::UNDERFLOW_BIN ); 00319 const int entries = h.binEntries( i ); 00320 if ( entries == 0 ) continue; 00321 const double newCentre = h.binMean( i ); 00322 const double newValue = h.binHeight( i ); 00323 if ( entries == 1 ) hist.fill( newCentre, newValue ); 00324 else { 00325 double newError = h.binError( i ); 00326 const double w1 = 00327 ( 2 * newValue - std::sqrt( ( 4 * entries * newError * newError - newValue * newValue ) / ( entries - 1 ) ) ) / ( 2 * entries ); 00328 const double w2 = newValue - ( entries - 1 ) * w1; 00329 for ( int ie = 0; ie < entries - 1; ++ie ) { 00330 hist.fill( newCentre, w1 ); 00331 } 00332 hist.fill( newCentre, w2 ); 00333 } 00334 } 00335 } 00336 else { 00337 for ( std::vector< Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::Cloud1DElement >::const_iterator iElement = m_elements.begin(); 00338 iElement != m_elements.end(); ++iElement ) { 00339 hist.fill( iElement->x, iElement->w ); 00340 } 00341 } 00342 return true; 00343 } 00344 00345 00346 bool 00347 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::setCacheSize( unsigned int newCacheSize ) 00348 { 00349 m_cacheSize = newCacheSize; 00350 if ( m_cacheSize != static_cast<unsigned int>( -1 ) ) m_elements.reserve( newCacheSize ); 00351 return true; 00352 } 00353 00354 00355 unsigned int 00356 Anaphe::AIDA_Histogram_native::AIDA_Cloud1D::cacheSize() const 00357 { 00358 return m_cacheSize; 00359 }