Warning, /include/GaudiAlg/GaudiHistos.icpp is written in an unsupported language. File is not indexed.
0001 /***********************************************************************************\
0002 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
0003 * *
0004 * This software is distributed under the terms of the Apache version 2 licence, *
0005 * copied verbatim in the file "LICENSE". *
0006 * *
0007 * In applying this licence, CERN does not waive the privileges and immunities *
0008 * granted to it by virtue of its status as an Intergovernmental Organization *
0009 * or submit itself to any jurisdiction. *
0010 \***********************************************************************************/
0011 #ifndef GAUDIALG_GAUDIHISTOS_ICPP
0012 #define GAUDIALG_GAUDIHISTOS_ICPP 1
0013 // ============================================================================
0014 /* @file
0015 *
0016 * Implementation file for class : GaudiHistos
0017 *
0018 * @author Chris Jones Christopher.Rob.Jones@cern.ch
0019 * @author Vanya BELYAEV Ivan.Belyaev@itep.ru
0020 * @date 2005-08-08
0021 */
0022 // ============================================================================
0023 // STD & STL
0024 // ============================================================================
0025 #include <algorithm>
0026 #include <cmath>
0027 #include <set>
0028 #include <string>
0029 #include <vector>
0030 // ============================================================================
0031 // GaudiKernel
0032 // ============================================================================
0033 #include "GaudiKernel/IHistogramSvc.h"
0034 #include "GaudiKernel/MsgStream.h"
0035 // ============================================================================
0036 // GaudiAlg
0037 // ============================================================================
0038 #include "GaudiAlg/Fill.h"
0039 #include "GaudiAlg/GaudiHistos.h"
0040 #include "GaudiAlg/HbookName.h"
0041 #include "GaudiAlg/Print.h"
0042 // ============================================================================
0043 // forward declarations from AIDA
0044 // ============================================================================
0045 namespace AIDA {
0046 class IBaseHistogram;
0047 class IHistogram;
0048 class IHistogram1D;
0049 class IHistogram2D;
0050 class IHistogram3D;
0051 class IProfile;
0052 class IProfile1D;
0053 class IProfile2D;
0054 } // namespace AIDA
0055 // ============================================================================
0056 // utility to allow iteration in order
0057 // ============================================================================
0058 namespace {
0059 constexpr struct ordered_t {
0060 template <typename C>
0061 std::map<typename C::key_type, typename C::mapped_type> operator()( const C& c ) const {
0062 return { std::begin( c ), std::end( c ) };
0063 }
0064 } ordered{};
0065
0066 template <typename Map>
0067 typename Map::mapped_type lookup_( const Map& map, const typename Map::key_type& ID ) {
0068 auto found = map.find( ID );
0069 return found != std::end( map ) ? found->second : nullptr;
0070 }
0071
0072 // ============================================================================
0073 // Searches 'title' for all instances of 'A' and replaces them with 'B'
0074 // ============================================================================
0075 inline void stringSearchReplace( std::string& title, const std::string& A, const std::string& B ) {
0076 for ( auto slash = title.find_first_of( A ); slash != std::string::npos; slash = title.find_first_of( A ) ) {
0077 title = title.substr( 0, slash ) + B + title.substr( slash + A.size() );
0078 }
0079 }
0080 } // namespace
0081 // ============================================================================
0082 // Initialise Histogramming
0083 // ============================================================================
0084 template <class PBASE>
0085 StatusCode GaudiHistos<PBASE>::
0086 #ifdef __ICC
0087 i_ghInitialize
0088 #else
0089 initialize
0090 #endif
0091 () {
0092 // initialize base class
0093 const StatusCode sc = PBASE::initialize();
0094 if ( sc.isFailure() ) return sc;
0095
0096 // produce histograms?
0097 if ( !produceHistos() ) {
0098 this->debug() << "Histogram production is switched OFF" << endmsg;
0099 return sc;
0100 }
0101
0102 // check the validity of histogram service
0103 if ( !this->histoSvc() ) { return this->Error( "initialize():: IHistogramSvc* is invalid" ); }
0104
0105 // Warn if the user has decided to use numerical automatic IDs
0106 if ( useNumericAutoIDs() ) {
0107 this->Warning(
0108 "Using numerical automatic IDs. These are not guaranteed to be totally deterministic. Use with care...",
0109 StatusCode::SUCCESS )
0110 .ignore();
0111 }
0112
0113 // Finally, print the location histogram will be written to
0114 this->Print( "The histogram path is set to be '" + histoPath() + "'", StatusCode::SUCCESS, MSG::DEBUG ).ignore();
0115
0116 return sc;
0117 }
0118 // ============================================================================
0119 // Finalise Histogramming
0120 // ============================================================================
0121 template <class PBASE>
0122 StatusCode GaudiHistos<PBASE>::
0123 #ifdef __ICC
0124 i_ghFinalize
0125 #else
0126 finalize
0127 #endif
0128 () {
0129
0130 if ( produceHistos() ) {
0131
0132 // Count how many histos of each type
0133 if ( ( !noHistos() ) && histoCountersPrint() ) {
0134 const unsigned int n1D = histo1DMapID().size();
0135 const unsigned int n2D = histo2DMapID().size();
0136 const unsigned int n3D = histo3DMapID().size();
0137 const unsigned int n1DP = profile1DMapID().size();
0138 const unsigned int n2DP = profile2DMapID().size();
0139 const unsigned int total = n1D + n2D + n3D + n1DP + n2DP;
0140 if ( total > 0 ) {
0141 this->always() << "Booked " << total << " Histogram(s) : ";
0142 if ( n1D > 0 ) this->always() << "1D=" << n1D << " ";
0143 if ( n2D > 0 ) this->always() << "2D=" << n2D << " ";
0144 if ( n3D > 0 ) this->always() << "3D=" << n3D << " ";
0145 if ( n1DP > 0 ) this->always() << "1DProf=" << n1DP << " ";
0146 if ( n2DP > 0 ) this->always() << "2DProf=" << n2DP << " ";
0147 this->always() << endmsg;
0148 }
0149 }
0150
0151 // detailed printing
0152 if ( histosPrint() ) { printHistos(); }
0153 }
0154
0155 // clear all maps
0156 m_histo1DMapTitle.clear();
0157 m_histo2DMapTitle.clear();
0158 m_histo3DMapTitle.clear();
0159 m_histo1DMapID.clear();
0160 m_histo2DMapID.clear();
0161 m_histo3DMapID.clear();
0162 m_profile1DMapTitle.clear();
0163 m_profile2DMapTitle.clear();
0164 m_profile1DMapID.clear();
0165 m_profile2DMapID.clear();
0166
0167 // finalize base class
0168 return PBASE::finalize();
0169 }
0170 // ============================================================================
0171 // perform the actual detailed printout of histograms
0172 // ============================================================================
0173 template <class PBASE>
0174 int GaudiHistos<PBASE>::printHistos( const MSG::Level level ) const {
0175 using namespace Gaudi::Utils::Histos;
0176
0177 if ( noHistos() ) {
0178 if ( this->msgLevel( MSG::DEBUG ) ) { this->msgStream( level ) << "No histograms are booked" << endmsg; }
0179 return 0; // RETURN
0180 }
0181
0182 MsgStream& msg = this->msgStream( level );
0183
0184 // Printout all histograms
0185
0186 if ( !histo1DMapID().empty() ) {
0187 msg << "1D histograms in directory "
0188 << "\"" << histoPath() << "\" : " << histo1DMapID().size();
0189 const Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
0190 if ( !table.header().empty() ) {
0191 msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
0192 }
0193 for ( const auto& entry : ordered( histo1DMapID() ) ) {
0194 const auto* aida = entry.second;
0195 if ( !aida ) {
0196 this->error() << "IHistogram1D points to NULL" << endmsg;
0197 continue;
0198 }
0199 // format and print the row
0200 msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
0201 }
0202 msg << endmsg;
0203 }
0204 // ==========================================================================
0205 if ( !histo2DMapID().empty() ) {
0206 msg << "2D histograms in directory "
0207 << "\"" << histoPath() << "\" : " << histo2DMapID().size();
0208
0209 for ( const auto& entry : ordered( histo2DMapID() ) ) {
0210 const auto* aida = entry.second;
0211 if ( !aida ) {
0212 this->error() << "IHistogram2D points to NULL" << endmsg;
0213 continue;
0214 }
0215 msg << std::endl << GaudiAlg::Print2D::toString( aida, entry.first );
0216 }
0217 msg << endmsg;
0218 }
0219 // ==========================================================================
0220 if ( !histo3DMapID().empty() ) {
0221 msg << "3D histograms in directory "
0222 << "\"" << histoPath() << "\" : " << histo3DMapID().size();
0223 for ( const auto& entry : ordered( histo3DMapID() ) ) {
0224 const auto* aida = entry.second;
0225 if ( !aida ) {
0226 this->error() << "IHistogram3D points to NULL" << endmsg;
0227 continue;
0228 }
0229 msg << std::endl << GaudiAlg::Print3D::toString( aida, entry.first );
0230 }
0231 msg << endmsg;
0232 }
0233 // ==========================================================================
0234 if ( !profile1DMapID().empty() ) {
0235 msg << "1D profile histograms in directory "
0236 << "\"" << histoPath() << "\" : " << profile1DMapID().size();
0237 const Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
0238 if ( !table.header().empty() ) {
0239 msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
0240 }
0241 for ( const auto& entry : ordered( profile1DMapID() ) ) {
0242 const auto* aida = entry.second;
0243 if ( !aida ) {
0244 this->error() << "IProfile1D points to NULL" << endmsg;
0245 continue;
0246 }
0247 msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
0248 }
0249 msg << endmsg;
0250 }
0251 // ==========================================================================
0252 if ( !profile2DMapID().empty() ) {
0253 msg << "2D profile histograms in directory "
0254 << "\"" << histoPath() << "\" : " << profile2DMapID().size();
0255 for ( const auto& entry : ordered( profile2DMapID() ) ) {
0256 const auto* aida = entry.second;
0257 if ( !aida ) {
0258 this->error() << "IProfile2D points to NULL" << endmsg;
0259 continue;
0260 }
0261 msg << std::endl << GaudiAlg::Print2DProf::toString( aida, entry.first );
0262 }
0263 msg << endmsg;
0264 }
0265 //
0266 return this->totalNumberOfHistos();
0267 }
0268 // ============================================================================
0269 // Check if all histogram maps are empty
0270 // ============================================================================
0271 template <class PBASE>
0272 bool GaudiHistos<PBASE>::noHistos() const {
0273 return ( histo1DMapTitle().empty() && histo2DMapTitle().empty() && histo3DMapTitle().empty() &&
0274 profile1DMapTitle().empty() && profile2DMapTitle().empty() && histo1DMapID().empty() &&
0275 histo2DMapID().empty() && histo3DMapID().empty() && profile1DMapID().empty() && profile2DMapID().empty() );
0276 }
0277 // ============================================================================
0278 // Declare a histogram to the monitor service
0279 // ============================================================================
0280 template <class PBASE>
0281 void GaudiHistos<PBASE>::monitorHisto( const AIDA::IBaseHistogram* hist, const HistoID& ID ) const {
0282 if ( hist && m_declareMoniHists ) {
0283 if ( this->msgLevel( MSG::DEBUG ) ) {
0284 this->debug() << "Monitoring histogram '" << ID.idAsString() << "' desc = '"
0285 << Gaudi::Utils::Histos::htitle( hist ) << "'" << endmsg;
0286 }
0287 this->declareInfo( histoPath() + "/" + ID.idAsString(), hist, Gaudi::Utils::Histos::htitle( hist ) );
0288 }
0289 }
0290 // ============================================================================
0291 // access the EXISTING 1D histogram by ID
0292 // ============================================================================
0293 template <class PBASE>
0294 AIDA::IHistogram1D* GaudiHistos<PBASE>::histo1D( const HistoID& ID ) const {
0295 return lookup_( histo1DMapID(), ID );
0296 }
0297 // ============================================================================
0298 // access the EXISTING 2D histogram by ID
0299 // ============================================================================
0300 template <class PBASE>
0301 AIDA::IHistogram2D* GaudiHistos<PBASE>::histo2D( const HistoID& ID ) const {
0302 return lookup_( histo2DMapID(), ID );
0303 }
0304 // ============================================================================
0305 // access the EXISTING 3D histogram by ID
0306 // ============================================================================
0307 template <class PBASE>
0308 AIDA::IHistogram3D* GaudiHistos<PBASE>::histo3D( const HistoID& ID ) const {
0309 return lookup_( histo3DMapID(), ID );
0310 }
0311 // ============================================================================
0312 // access the EXISTING 1D profile histogram by ID
0313 // ============================================================================
0314 template <class PBASE>
0315 AIDA::IProfile1D* GaudiHistos<PBASE>::profile1D( const HistoID& ID ) const {
0316 return lookup_( profile1DMapID(), ID );
0317 }
0318 // ============================================================================
0319 // access the EXISTING 2D profile histogram by ID
0320 // ============================================================================
0321 template <class PBASE>
0322 AIDA::IProfile2D* GaudiHistos<PBASE>::profile2D( const HistoID& ID ) const {
0323 return lookup_( profile2DMapID(), ID );
0324 }
0325 // ============================================================================
0326 // Returns the total number of histograms (of all types) currently booked
0327 // ============================================================================
0328 template <class PBASE>
0329 unsigned int GaudiHistos<PBASE>::totalNumberOfHistos() const {
0330 return histo1DMapID().size() + histo2DMapID().size() + histo3DMapID().size() + profile1DMapID().size() +
0331 profile2DMapID().size();
0332 }
0333 // ============================================================================
0334 // Create a new histogram ID using the given title
0335 // ============================================================================
0336 template <class PBASE>
0337 void GaudiHistos<PBASE>::newHistoID( const std::string& title, HistoID& ID ) const {
0338 if ( useNumericAutoIDs() || title.empty() ) {
0339 if ( !useNumericAutoIDs() ) {
0340 this->Warning(
0341 "Cannot generate automatic literal ID from an empty title ! Using numeric ID instead for histogram ID",
0342 StatusCode::SUCCESS )
0343 .ignore();
0344 }
0345 // propose the histogram ID (always numeric)
0346 ID = HistoID( totalNumberOfHistos() + 1 + histoOffSet() );
0347 // adjust the proposed ID
0348 while ( histoExists( ID ) ) { ID = HistoID( ID.numeric() + 1 ); }
0349 } else {
0350 // use the title to create a unique literal ID
0351 ID = HistoID( this->convertTitleToID( title ) );
0352 // Just in case ...
0353 while ( histoExists( ID ) ) { ID = HistoID( ID.idAsString() + "_" ); }
0354 }
0355 }
0356 // ============================================================================
0357 // Create an ID string from a title string
0358 // ============================================================================
0359 template <class PBASE>
0360 std::string GaudiHistos<PBASE>::convertTitleToID( std::string title ) const {
0361 // clean up the ID string for all unwanted characters
0362 for ( const auto& i : m_idReplaceInfo ) { stringSearchReplace( title, i.first, i.second ); }
0363 return title;
0364 }
0365 // get the constructed histogram path
0366 // ============================================================================
0367 template <class PBASE>
0368 std::string GaudiHistos<PBASE>::histoPath() const {
0369 std::string path = histoTopDir() + histoDir();
0370 return splitHistoDir() ? dirHbookName( path ) : path;
0371 }
0372 // ============================================================================
0373 // 1D
0374 #include "GaudiAlg/GaudiHistos_1DFixedBinning.icpp"
0375 #include "GaudiAlg/GaudiHistos_1DVariableBinning.icpp"
0376 // 2D
0377 #include "GaudiAlg/GaudiHistos_2DFixedBinning.icpp"
0378 #include "GaudiAlg/GaudiHistos_2DVariableBinning.icpp"
0379 // 3D
0380 #include "GaudiAlg/GaudiHistos_3DFixedBinning.icpp"
0381 #include "GaudiAlg/GaudiHistos_3DVariableBinning.icpp"
0382 // 1D Profile
0383 #include "GaudiAlg/GaudiHistos_1DProfFixedBinning.icpp"
0384 #include "GaudiAlg/GaudiHistos_1DProfVariableBinning.icpp"
0385 // 2D Profile
0386 #include "GaudiAlg/GaudiHistos_2DProfFixedBinning.icpp"
0387 #include "GaudiAlg/GaudiHistos_2DProfVariableBinning.icpp"
0388 // ============================================================================
0389 // The END
0390 // ============================================================================
0391 #endif // GAUDIALG_GAUDIHISTOS_ICPP