00001
00002
00003 #ifndef GAUDIALG_GAUDIHISTOS_ICPP
00004 #define GAUDIALG_GAUDIHISTOS_ICPP 1
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <algorithm>
00018 #include <string>
00019 #include <vector>
00020 #include <set>
00021
00022
00023
00024 #include "GaudiKernel/MsgStream.h"
00025 #include "GaudiKernel/IHistogramSvc.h"
00026
00027
00028
00029 #include "GaudiUtils/HistoTableFormat.h"
00030
00031
00032
00033 #include "GaudiAlg/GaudiHistos.h"
00034 #include "GaudiAlg/CheckForNaN.h"
00035 #include "GaudiAlg/Print.h"
00036 #include "GaudiAlg/Fill.h"
00037
00038
00039
00040 namespace AIDA
00041 {
00042 class IBaseHistogram ;
00043 class IHistogram ;
00044 class IHistogram1D ;
00045 class IHistogram2D ;
00046 class IHistogram3D ;
00047 class IProfile ;
00048 class IProfile1D ;
00049 class IProfile2D ;
00050 }
00051
00052
00053
00054 template <class PBASE>
00055 GaudiHistos<PBASE>::~GaudiHistos() {}
00056
00057
00058
00059 template <class PBASE>
00060 void GaudiHistos<PBASE>::initGaudiHistosConstructor()
00061 {
00062
00063 this->declareProperty
00064 ( "HistoProduce" ,
00065 m_produceHistos = true ,
00066 "Swith on/off the production of histograms " ) ;
00067
00068 this->declareProperty
00069 ( "HistoPrint" ,
00070 m_histosPrint = false ,
00071 "Switch on/off the printout of histograms at finalization" )
00072 -> declareUpdateHandler ( &GaudiHistos<PBASE>::printHistoHandler, this ) ;
00073
00074 this->declareProperty
00075 ( "HistoCheckForNaN" ,
00076 m_checkForNaN = true ,
00077 "Swicth on/off the checks for NaN and Infinity for histogram fill" ) ;
00078
00079 this->declareProperty
00080 ( "HistoSplitDir" ,
00081 m_splitHistoDir = false ,
00082 "Split long directory names into short pieces (suitable for HBOOK)" );
00083
00084 this->declareProperty
00085 ( "HistoOffSet" ,
00086 m_histoOffSet = 0 ,
00087 "OffSet for automatically assigned histogram numerical identifiers " ) ;
00088
00089 this->declareProperty
00090 ( "HistoTopDir" ,
00091 m_histoTopDir = "" ,
00092 "Top level histogram directory (take care that it ends with '/')" ) ;
00093
00094 this->declareProperty
00095 ( "HistoDir" ,
00096 m_histoDir = this->name() ,
00097 "Histogram Directory" ) ;
00098
00099 this->declareProperty ( "FullDetail" , m_fullDetail = false ) ;
00100
00101 this->declareProperty ( "MonitorHistograms" , m_declareMoniHists = true ) ;
00102
00103 this->declareProperty
00104 ( "FormatFor1DHistoTable" ,
00105 m_histo1DTableFormat = Gaudi::Utils::Histos::Formats::format () ,
00106 "Format string for printout of 1D histograms" ) ;
00107
00108 this->declareProperty
00109 ( "ShortFormatFor1DHistoTable" ,
00110 m_histo1DTableFormatShort = " | %1$-25.25s %2%" ,
00111 "Format string for printout of 1D histograms" ) ;
00112
00113 this->declareProperty
00114 ( "HeaderFor1DHistoTable" ,
00115 m_histo1DTableHeader = Gaudi::Utils::Histos::Formats::header () ,
00116 "The table header for printout of 1D histograms " ) ;
00117 this->declareProperty
00118 ( "UseSequencialNumericAutoIDs", m_useNumericAutoIDs = false,
00119 "Flag to allow users to switch back to the old style of creating numerical automatic IDs" );
00120 m_idReplaceInfo.clear();
00121 m_idReplaceInfo["/"] = "=SLASH=";
00122 this->declareProperty
00123 ( "AutoStringIDPurgeMap", m_idReplaceInfo,
00124 "Map of strings to search and replace when using the title as the basis of automatically generated literal IDs" );
00125 }
00126
00127
00128
00129 template <class PBASE>
00130 StatusCode GaudiHistos<PBASE>::initialize()
00131 {
00132
00133 const StatusCode sc = PBASE::initialize();
00134 if ( sc.isFailure() ) return sc;
00135
00136
00137 if ( !produceHistos() )
00138 {
00139 this->debug() << "Histogram production is switched OFF" << endmsg;
00140 return sc;
00141 }
00142
00143
00144 if ( this->histoSvc() == NULL )
00145 { return this->Error("initialize():: IHistogramSvc* is invalid"); }
00146
00147
00148 if ( useNumericAutoIDs() )
00149 {
00150 this ->
00151 Warning( "Using numerical automatic IDs. These are not guaranteed to be totally deterministic. Use with care...",
00152 StatusCode::SUCCESS );
00153 }
00154
00155
00156 Print
00157 ( "The histogram path is set to be '" + histoPath() + "'",
00158 StatusCode( StatusCode::SUCCESS, true ) , MSG::DEBUG );
00159
00160 return sc;
00161 }
00162
00163
00164
00165 template <class PBASE>
00166 StatusCode GaudiHistos<PBASE>::finalize()
00167 {
00168
00169 if ( produceHistos() )
00170 {
00171
00172
00173 if ( !noHistos() )
00174 {
00175 const unsigned int n1D = histo1DMapID () . size () ;
00176 const unsigned int n2D = histo2DMapID () . size () ;
00177 const unsigned int n3D = histo3DMapID () . size () ;
00178 const unsigned int n1DP = profile1DMapID () . size () ;
00179 const unsigned int n2DP = profile2DMapID () . size () ;
00180 const unsigned int total = n1D+n2D+n3D+n1DP+n2DP;
00181 if ( total>0 )
00182 {
00183 this->always() << "Booked " << total << " Histogram(s) : ";
00184 if ( n1D>0 ) this->always() << "1D=" << n1D << " ";
00185 if ( n2D>0 ) this->always() << "2D=" << n2D << " ";
00186 if ( n3D>0 ) this->always() << "3D=" << n3D << " ";
00187 if ( n1DP>0 ) this->always() << "1DProf=" << n1DP << " ";
00188 if ( n2DP>0 ) this->always() << "2DProf=" << n2DP << " ";
00189 this->always() << endmsg;
00190 }
00191 }
00192
00193
00194 if ( histosPrint() ) { printHistos() ; }
00195
00196 }
00197
00198
00199 m_histo1DMapTitle . clear () ;
00200 m_histo2DMapTitle . clear () ;
00201 m_histo3DMapTitle . clear () ;
00202 m_histo1DMapID . clear () ;
00203 m_histo2DMapID . clear () ;
00204 m_histo3DMapID . clear () ;
00205 m_profile1DMapTitle . clear () ;
00206 m_profile2DMapTitle . clear () ;
00207 m_profile1DMapID . clear () ;
00208 m_profile2DMapID . clear () ;
00209
00210
00211 return PBASE::finalize();
00212 }
00213
00214
00215
00216 template <class PBASE>
00217 int GaudiHistos<PBASE>::printHistos ( const MSG::Level level ) const
00218 {
00219 using namespace Gaudi::Utils::Histos ;
00220
00221 if ( noHistos() )
00222 {
00223 if ( this->msgLevel(MSG::DEBUG) )
00224 { this->msgStream(level) << "No histograms are booked" << endmsg ; }
00225 return 0 ;
00226 }
00227
00228 MsgStream & msg = this->msgStream(level);
00229
00230
00231
00232 Gaudi::Utils::Histos::Table table
00233 ( m_histo1DTableFormat ,
00234 m_histo1DTableHeader ) ;
00235
00236 if ( !histo1DMapID().empty() )
00237 {
00238 msg << "List of booked 1D histograms in directory "
00239 << "\"" << histoPath() << "\" :-" ;
00240
00241 if ( !table.header().empty() )
00242 {
00243 msg << std::endl << Gaudi::Utils::Histos::format
00244 ( "ID" , table.header() , m_histo1DTableFormatShort ) ;
00245 }
00246
00247 typedef std::map<HistoID,const AIDA::IHistogram1D*> OrderedMapType;
00248 OrderedMapType OrderedMap ( histo1DMapID().begin() , histo1DMapID().end() );
00249
00250 for ( OrderedMapType::const_iterator entry = OrderedMap.begin() ;
00251 OrderedMap.end() != entry ; ++entry )
00252 {
00253 const AIDA::IHistogram1D* aida = entry->second ;
00254 if ( NULL == aida )
00255 { this->error() << "IHistogram1D points to NULL" << endmsg ; continue ; }
00256
00257 msg << std::endl << table.toString
00258 ( aida ,
00259 HistoID ( entry->first ) ,
00260 m_histo1DTableFormatShort ) ;
00261 }
00262 msg << endmsg ;
00263 }
00264
00265 if ( !histo2DMapID().empty() )
00266 {
00267 msg << "List of booked 2D histograms in directory "
00268 << "\"" << histoPath() << "\" :-" ;
00269
00270
00271 typedef std::map<HistoID,const AIDA::IHistogram2D*> OrderedMapType;
00272 OrderedMapType OrderedMap ( histo2DMapID().begin() , histo2DMapID().end() ) ;
00273
00274 for ( OrderedMapType::const_iterator entry = OrderedMap.begin() ;
00275 OrderedMap.end() != entry ; ++entry )
00276 {
00277 const AIDA::IHistogram2D* aida = entry->second ;
00278 if ( NULL == aida )
00279 { this->error() << "IHistogram2D points to NULL" << endmsg ; continue ; }
00280 msg << std::endl
00281 << GaudiAlg::Print2D::toString ( aida , entry->first );
00282 }
00283 msg << endmsg ;
00284 }
00285
00286 if ( !histo3DMapID().empty() )
00287 {
00288 msg << "List of booked 3D histograms in directory "
00289 << "\"" << histoPath() << "\" :-" ;
00290
00291 typedef std::map<HistoID,const AIDA::IHistogram3D*> OrderedMapType;
00292 OrderedMapType OrderedMap ( histo3DMapID().begin() , histo3DMapID().end() ) ;
00293
00294 for ( OrderedMapType::const_iterator entry = OrderedMap.begin() ;
00295 OrderedMap.end() != entry ; ++entry )
00296 {
00297 const AIDA::IHistogram3D* aida = entry->second ;
00298 if ( NULL == aida )
00299 { this->error() << "IHistogram3D points to NULL" << endmsg ; continue ; }
00300 msg << std::endl << GaudiAlg::Print3D::toString ( aida , entry->first );
00301 }
00302 msg << endmsg ;
00303 }
00304
00305 if ( !profile1DMapID().empty() )
00306 {
00307 msg << "List of booked 1D profile histograms in directory "
00308 << "\"" << histoPath() << "\" :-" ;
00309
00310 typedef std::map<HistoID,const AIDA::IProfile1D*> OrderedMapType;
00311 OrderedMapType OrderedMap ( profile1DMapID().begin() , profile1DMapID().end() ) ;
00312
00313 for ( OrderedMapType::const_iterator entry = OrderedMap.begin() ;
00314 OrderedMap.end() != entry ; ++entry )
00315 {
00316 const AIDA::IProfile1D* aida = entry->second ;
00317 if ( NULL == aida )
00318 { this->error() << "IProfile1D points to NULL" << endmsg ; continue ; }
00319 msg << std::endl << GaudiAlg::Print1DProf::toString ( aida , entry->first );
00320 }
00321 msg << endmsg ;
00322 }
00323
00324 if ( !profile2DMapID().empty() )
00325 {
00326 msg << "List of booked 2D profile histograms in directory "
00327 << "\"" << histoPath() << "\" :-" ;
00328
00329 typedef std::map<HistoID,const AIDA::IProfile2D*> OrderedMapType;
00330 OrderedMapType OrderedMap ( profile2DMapID().begin() , profile2DMapID().end() ) ;
00331
00332 for ( OrderedMapType::const_iterator entry = OrderedMap.begin() ;
00333 OrderedMap.end() != entry ; ++entry )
00334 {
00335 const AIDA::IProfile2D* aida = entry->second ;
00336 if ( NULL == aida )
00337 { this->error() << "IProfile2D points to NULL" << endmsg ; continue ; }
00338 msg << std::endl << GaudiAlg::Print2DProf::toString ( aida , entry->first );
00339 }
00340 msg << endmsg ;
00341 }
00342
00343 return this->totalNumberOfHistos() ;
00344 }
00345
00346
00347
00348 template <class PBASE>
00349 bool GaudiHistos<PBASE>::noHistos() const
00350 {
00351 return ( histo1DMapTitle () . empty() &&
00352 histo2DMapTitle () . empty() &&
00353 histo3DMapTitle () . empty() &&
00354 profile1DMapTitle () . empty() &&
00355 profile2DMapTitle () . empty() &&
00356 histo1DMapID () . empty() &&
00357 histo2DMapID () . empty() &&
00358 histo3DMapID () . empty() &&
00359 profile1DMapID () . empty() &&
00360 profile2DMapID () . empty() );
00361 }
00362
00363
00364
00365 template <class PBASE>
00366 void GaudiHistos<PBASE>::monitorHisto
00367 ( const AIDA::IBaseHistogram* hist,
00368 const HistoID& ID ) const
00369 {
00370 if ( hist && m_declareMoniHists )
00371 {
00372 if ( this->msgLevel(MSG::DEBUG) )
00373 {
00374 this->debug() << "Monitoring histogram '"
00375 << ID.idAsString() << "' desc = '"
00376 << Gaudi::Utils::Histos::htitle(hist) << "'" << endmsg;
00377 }
00378 this->declareInfo ( histoPath()+"/"+ID.idAsString() ,
00379 hist ,
00380 Gaudi::Utils::Histos::htitle(hist) ) ;
00381 }
00382 }
00383
00384
00385
00386 template <class PBASE>
00387 AIDA::IHistogram1D* GaudiHistos<PBASE>::histo1D ( const HistoID& ID ) const
00388 {
00389 AIDA::IHistogram1D * h(NULL);
00390
00391 Histo1DMapID::const_iterator found = histo1DMapID().find( ID ) ;
00392
00393 h = ( histo1DMapID().end() == found ? NULL : found->second );
00394
00395 return h ;
00396 }
00397
00398
00399
00400 template <class PBASE>
00401 AIDA::IHistogram2D* GaudiHistos<PBASE>::histo2D ( const HistoID& ID ) const
00402 {
00403 AIDA::IHistogram2D * h(NULL);
00404
00405 Histo2DMapID::const_iterator found = histo2DMapID().find( ID ) ;
00406
00407 h = ( histo2DMapID().end() == found ? NULL : found->second );
00408
00409 return h;
00410 }
00411
00412
00413
00414 template <class PBASE>
00415 AIDA::IHistogram3D* GaudiHistos<PBASE>::histo3D ( const HistoID& ID ) const
00416 {
00417 AIDA::IHistogram3D * h(NULL);
00418
00419 Histo3DMapID::const_iterator found = histo3DMapID().find( ID ) ;
00420 h = ( histo3DMapID().end() == found ? NULL : found->second );
00421
00422 return h;
00423 }
00424
00425
00426
00427 template <class PBASE>
00428 AIDA::IProfile1D* GaudiHistos<PBASE>::profile1D ( const HistoID& ID ) const
00429 {
00430 AIDA::IProfile1D * h(NULL);
00431
00432 Profile1DMapID::const_iterator found = profile1DMapID().find( ID ) ;
00433
00434 h = ( profile1DMapID().end() == found ? NULL : found->second );
00435
00436 return h;
00437 }
00438
00439
00440
00441 template <class PBASE>
00442 AIDA::IProfile2D* GaudiHistos<PBASE>::profile2D ( const HistoID& ID ) const
00443 {
00444 AIDA::IProfile2D * h(NULL);
00445
00446 Profile2DMapID::const_iterator found = profile2DMapID().find( ID ) ;
00447
00448 h = ( profile2DMapID().end() == found ? NULL : found->second );
00449
00450 return h;
00451 }
00452
00453
00454
00455 template <class PBASE>
00456 unsigned int GaudiHistos<PBASE>::totalNumberOfHistos() const
00457 {
00458 return
00459 histo1DMapID () . size () +
00460 histo2DMapID () . size () +
00461 histo3DMapID () . size () +
00462 profile1DMapID () . size () +
00463 profile2DMapID () . size () ;
00464 }
00465
00466
00467
00468 template <class PBASE>
00469 void GaudiHistos<PBASE>::newHistoID
00470 ( const std::string & title ,
00471 HistoID& ID ) const
00472 {
00473 if ( useNumericAutoIDs() || title.empty() )
00474 {
00475 if ( !useNumericAutoIDs() )
00476 {
00477 this -> Warning( "Cannot generate automatic literal ID from an empty title ! Using numeric ID instead for histogram ID",
00478 StatusCode::SUCCESS );
00479 }
00480
00481 ID = HistoID( totalNumberOfHistos() + 1 + histoOffSet() );
00482
00483 while ( histoExists( ID ) ) { ID = HistoID ( ID.numeric() + 1 ) ; }
00484 }
00485 else
00486 {
00487
00488 ID = HistoID( this->convertTitleToID(title) );
00489
00490 while ( histoExists( ID ) ) { ID = HistoID(ID.idAsString()+"_"); }
00491 }
00492 }
00493
00494
00495
00496 template <class PBASE>
00497 std::string GaudiHistos<PBASE>::convertTitleToID( const std::string & title ) const
00498 {
00499
00500 std::string tmp_id = title;
00501 for ( std::map<std::string,std::string>::const_iterator i =
00502 m_idReplaceInfo.begin() ; i != m_idReplaceInfo.end(); ++i )
00503 {
00504 stringSearchReplace( tmp_id, i->first, i->second );
00505 }
00506 return tmp_id;
00507 }
00508
00509
00510
00511 template <class PBASE>
00512 void GaudiHistos<PBASE>::stringSearchReplace
00513 ( std::string & title ,
00514 const std::string & A ,
00515 const std::string & B ) const
00516 {
00517 std::string::size_type slash = title.find_first_of ( A ) ;
00518 while ( std::string::npos != slash )
00519 {
00520 title = title.substr(0,slash) + B + title.substr(slash+A.size());
00521 slash = title.find_first_of( A );
00522 }
00523 }
00524
00525
00526
00527 template < class PBASE >
00528 void GaudiHistos<PBASE>::printHistoHandler( Property& )
00529 {
00530
00531 if ( this -> FSMState() < Gaudi::StateMachine::INITIALIZED ) { return ; }
00532 if ( this -> histosPrint() ) { this -> printHistos ( MSG::ALWAYS ) ; }
00533 }
00534
00535
00536 #include "GaudiAlg/GaudiHistos_1DFixedBinning.icpp"
00537 #include "GaudiAlg/GaudiHistos_1DVariableBinning.icpp"
00538
00539 #include "GaudiAlg/GaudiHistos_2DFixedBinning.icpp"
00540 #include "GaudiAlg/GaudiHistos_2DVariableBinning.icpp"
00541
00542 #include "GaudiAlg/GaudiHistos_3DFixedBinning.icpp"
00543 #include "GaudiAlg/GaudiHistos_3DVariableBinning.icpp"
00544
00545 #include "GaudiAlg/GaudiHistos_1DProfFixedBinning.icpp"
00546 #include "GaudiAlg/GaudiHistos_1DProfVariableBinning.icpp"
00547
00548 #include "GaudiAlg/GaudiHistos_2DProfFixedBinning.icpp"
00549 #include "GaudiAlg/GaudiHistos_2DProfVariableBinning.icpp"
00550
00551
00552
00553 #endif // GAUDIALG_GAUDIHISTOS_ICPP
00554