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