The Gaudi Framework  v33r1 (b1225454)
GaudiHistos.icpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 #ifndef GAUDIALG_GAUDIHISTOS_ICPP
12 #define GAUDIALG_GAUDIHISTOS_ICPP 1
13 // ============================================================================
14 /* @file
15  *
16  * Implementation file for class : GaudiHistos
17  *
18  * @author Chris Jones Christopher.Rob.Jones@cern.ch
19  * @author Vanya BELYAEV Ivan.Belyaev@itep.ru
20  * @date 2005-08-08
21  */
22 // ============================================================================
23 // STD & STL
24 // ============================================================================
25 #include <algorithm>
26 #include <cmath>
27 #include <set>
28 #include <string>
29 #include <vector>
30 // ============================================================================
31 // GaudiKernel
32 // ============================================================================
34 #include "GaudiKernel/MsgStream.h"
35 // ============================================================================
36 // GaudiAlg
37 // ============================================================================
38 #include "GaudiAlg/Fill.h"
39 #include "GaudiAlg/GaudiHistos.h"
40 #include "GaudiAlg/HbookName.h"
41 #include "GaudiAlg/Print.h"
42 // ============================================================================
43 // forward declarations from AIDA
44 // ============================================================================
45 namespace AIDA {
46  class IBaseHistogram;
47  class IHistogram;
48  class IHistogram1D;
49  class IHistogram2D;
50  class IHistogram3D;
51  class IProfile;
52  class IProfile1D;
53  class IProfile2D;
54 } // namespace AIDA
55 // ============================================================================
56 // utility to allow iteration in order
57 // ============================================================================
58 namespace {
59  constexpr struct ordered_t {
60  template <typename C>
61  std::map<typename C::key_type, typename C::mapped_type> operator()( const C& c ) const {
62  return {std::begin( c ), std::end( c )};
63  }
64  } ordered{};
65 
66  template <typename Map>
67  typename Map::mapped_type lookup_( const Map& map, const typename Map::key_type& ID ) {
68  auto found = map.find( ID );
69  return found != std::end( map ) ? found->second : nullptr;
70  }
71 
72  // ============================================================================
73  // Searches 'title' for all instances of 'A' and replaces them with 'B'
74  // ============================================================================
75  inline void stringSearchReplace( std::string& title, const std::string& A, const std::string& B ) {
76  for ( auto slash = title.find_first_of( A ); slash != std::string::npos; slash = title.find_first_of( A ) ) {
77  title = title.substr( 0, slash ) + B + title.substr( slash + A.size() );
78  }
79  }
80 } // namespace
81 // ============================================================================
82 // Initialise Histogramming
83 // ============================================================================
84 template <class PBASE>
86 #ifdef __ICC
87  i_ghInitialize
88 #else
89  initialize
90 #endif
91  () {
92  // initialize base class
93  const StatusCode sc = PBASE::initialize();
94  if ( sc.isFailure() ) return sc;
95 
96  // produce histograms?
97  if ( !produceHistos() ) {
98  this->debug() << "Histogram production is switched OFF" << endmsg;
99  return sc;
100  }
101 
102  // check the validity of histogram service
103  if ( !this->histoSvc() ) { return this->Error( "initialize():: IHistogramSvc* is invalid" ); }
104 
105  // Warn if the user has decided to use numerical automatic IDs
106  if ( useNumericAutoIDs() ) {
107  this->Warning(
108  "Using numerical automatic IDs. These are not guaranteed to be totally deterministic. Use with care...",
110  .ignore();
111  }
112 
113  // Finally, print the location histogram will be written to
114  this->Print( "The histogram path is set to be '" + histoPath() + "'", StatusCode( StatusCode::SUCCESS, true ),
115  MSG::DEBUG )
116  .ignore();
117 
118  return sc;
119 }
120 // ============================================================================
121 // Finalise Histogramming
122 // ============================================================================
123 template <class PBASE>
125 #ifdef __ICC
126  i_ghFinalize
127 #else
128  finalize
129 #endif
130  () {
131 
132  if ( produceHistos() ) {
133 
134  // Count how many histos of each type
135  if ( ( !noHistos() ) && histoCountersPrint() ) {
136  const unsigned int n1D = histo1DMapID().size();
137  const unsigned int n2D = histo2DMapID().size();
138  const unsigned int n3D = histo3DMapID().size();
139  const unsigned int n1DP = profile1DMapID().size();
140  const unsigned int n2DP = profile2DMapID().size();
141  const unsigned int total = n1D + n2D + n3D + n1DP + n2DP;
142  if ( total > 0 ) {
143  this->always() << "Booked " << total << " Histogram(s) : ";
144  if ( n1D > 0 ) this->always() << "1D=" << n1D << " ";
145  if ( n2D > 0 ) this->always() << "2D=" << n2D << " ";
146  if ( n3D > 0 ) this->always() << "3D=" << n3D << " ";
147  if ( n1DP > 0 ) this->always() << "1DProf=" << n1DP << " ";
148  if ( n2DP > 0 ) this->always() << "2DProf=" << n2DP << " ";
149  this->always() << endmsg;
150  }
151  }
152 
153  // detailed printing
154  if ( histosPrint() ) { printHistos(); }
155  }
156 
157  // clear all maps
158  m_histo1DMapTitle.clear();
159  m_histo2DMapTitle.clear();
160  m_histo3DMapTitle.clear();
161  m_histo1DMapID.clear();
162  m_histo2DMapID.clear();
163  m_histo3DMapID.clear();
164  m_profile1DMapTitle.clear();
165  m_profile2DMapTitle.clear();
166  m_profile1DMapID.clear();
167  m_profile2DMapID.clear();
168 
169  // finalize base class
170  return PBASE::finalize();
171 }
172 // ============================================================================
173 // perform the actual detailed printout of histograms
174 // ============================================================================
175 template <class PBASE>
177  using namespace Gaudi::Utils::Histos;
178 
179  if ( noHistos() ) {
180  if ( this->msgLevel( MSG::DEBUG ) ) { this->msgStream( level ) << "No histograms are booked" << endmsg; }
181  return 0; // RETURN
182  }
183 
184  MsgStream& msg = this->msgStream( level );
185 
186  // Printout all histograms
187 
188  if ( !histo1DMapID().empty() ) {
189  msg << "1D histograms in directory "
190  << "\"" << histoPath() << "\" : " << histo1DMapID().size();
191  const Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
192  if ( !table.header().empty() ) {
193  msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
194  }
195  for ( const auto& entry : ordered( histo1DMapID() ) ) {
196  const auto* aida = entry.second;
197  if ( !aida ) {
198  this->error() << "IHistogram1D points to NULL" << endmsg;
199  continue;
200  }
201  // format and print the row
202  msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
203  }
204  msg << endmsg;
205  }
206  // ==========================================================================
207  if ( !histo2DMapID().empty() ) {
208  msg << "2D histograms in directory "
209  << "\"" << histoPath() << "\" : " << histo2DMapID().size();
210 
211  for ( const auto& entry : ordered( histo2DMapID() ) ) {
212  const auto* aida = entry.second;
213  if ( !aida ) {
214  this->error() << "IHistogram2D points to NULL" << endmsg;
215  continue;
216  }
217  msg << std::endl << GaudiAlg::Print2D::toString( aida, entry.first );
218  }
219  msg << endmsg;
220  }
221  // ==========================================================================
222  if ( !histo3DMapID().empty() ) {
223  msg << "3D histograms in directory "
224  << "\"" << histoPath() << "\" : " << histo3DMapID().size();
225  for ( const auto& entry : ordered( histo3DMapID() ) ) {
226  const auto* aida = entry.second;
227  if ( !aida ) {
228  this->error() << "IHistogram3D points to NULL" << endmsg;
229  continue;
230  }
231  msg << std::endl << GaudiAlg::Print3D::toString( aida, entry.first );
232  }
233  msg << endmsg;
234  }
235  // ==========================================================================
236  if ( !profile1DMapID().empty() ) {
237  msg << "1D profile histograms in directory "
238  << "\"" << histoPath() << "\" : " << profile1DMapID().size();
239  const Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
240  if ( !table.header().empty() ) {
241  msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
242  }
243  for ( const auto& entry : ordered( profile1DMapID() ) ) {
244  const auto* aida = entry.second;
245  if ( !aida ) {
246  this->error() << "IProfile1D points to NULL" << endmsg;
247  continue;
248  }
249  msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
250  }
251  msg << endmsg;
252  }
253  // ==========================================================================
254  if ( !profile2DMapID().empty() ) {
255  msg << "2D profile histograms in directory "
256  << "\"" << histoPath() << "\" : " << profile2DMapID().size();
257  for ( const auto& entry : ordered( profile2DMapID() ) ) {
258  const auto* aida = entry.second;
259  if ( !aida ) {
260  this->error() << "IProfile2D points to NULL" << endmsg;
261  continue;
262  }
263  msg << std::endl << GaudiAlg::Print2DProf::toString( aida, entry.first );
264  }
265  msg << endmsg;
266  }
267  //
268  return this->totalNumberOfHistos();
269 }
270 // ============================================================================
271 // Check if all histogram maps are empty
272 // ============================================================================
273 template <class PBASE>
275  return ( histo1DMapTitle().empty() && histo2DMapTitle().empty() && histo3DMapTitle().empty() &&
276  profile1DMapTitle().empty() && profile2DMapTitle().empty() && histo1DMapID().empty() &&
277  histo2DMapID().empty() && histo3DMapID().empty() && profile1DMapID().empty() && profile2DMapID().empty() );
278 }
279 // ============================================================================
280 // Declare a histogram to the monitor service
281 // ============================================================================
282 template <class PBASE>
283 void GaudiHistos<PBASE>::monitorHisto( const AIDA::IBaseHistogram* hist, const HistoID& ID ) const {
284  if ( hist && m_declareMoniHists ) {
285  if ( this->msgLevel( MSG::DEBUG ) ) {
286  this->debug() << "Monitoring histogram '" << ID.idAsString() << "' desc = '"
287  << Gaudi::Utils::Histos::htitle( hist ) << "'" << endmsg;
288  }
289  this->declareInfo( histoPath() + "/" + ID.idAsString(), hist, Gaudi::Utils::Histos::htitle( hist ) );
290  }
291 }
292 // ============================================================================
293 // access the EXISTING 1D histogram by ID
294 // ============================================================================
295 template <class PBASE>
296 AIDA::IHistogram1D* GaudiHistos<PBASE>::histo1D( const HistoID& ID ) const {
297  return lookup_( histo1DMapID(), ID );
298 }
299 // ============================================================================
300 // access the EXISTING 2D histogram by ID
301 // ============================================================================
302 template <class PBASE>
303 AIDA::IHistogram2D* GaudiHistos<PBASE>::histo2D( const HistoID& ID ) const {
304  return lookup_( histo2DMapID(), ID );
305 }
306 // ============================================================================
307 // access the EXISTING 3D histogram by ID
308 // ============================================================================
309 template <class PBASE>
310 AIDA::IHistogram3D* GaudiHistos<PBASE>::histo3D( const HistoID& ID ) const {
311  return lookup_( histo3DMapID(), ID );
312 }
313 // ============================================================================
314 // access the EXISTING 1D profile histogram by ID
315 // ============================================================================
316 template <class PBASE>
317 AIDA::IProfile1D* GaudiHistos<PBASE>::profile1D( const HistoID& ID ) const {
318  return lookup_( profile1DMapID(), ID );
319 }
320 // ============================================================================
321 // access the EXISTING 2D profile histogram by ID
322 // ============================================================================
323 template <class PBASE>
324 AIDA::IProfile2D* GaudiHistos<PBASE>::profile2D( const HistoID& ID ) const {
325  return lookup_( profile2DMapID(), ID );
326 }
327 // ============================================================================
328 // Returns the total number of histograms (of all types) currently booked
329 // ============================================================================
330 template <class PBASE>
332  return histo1DMapID().size() + histo2DMapID().size() + histo3DMapID().size() + profile1DMapID().size() +
333  profile2DMapID().size();
334 }
335 // ============================================================================
336 // Create a new histogram ID using the given title
337 // ============================================================================
338 template <class PBASE>
339 void GaudiHistos<PBASE>::newHistoID( const std::string& title, HistoID& ID ) const {
340  if ( useNumericAutoIDs() || title.empty() ) {
341  if ( !useNumericAutoIDs() ) {
342  this->Warning(
343  "Cannot generate automatic literal ID from an empty title ! Using numeric ID instead for histogram ID",
345  .ignore();
346  }
347  // propose the histogram ID (always numeric)
348  ID = HistoID( totalNumberOfHistos() + 1 + histoOffSet() );
349  // adjust the proposed ID
350  while ( histoExists( ID ) ) { ID = HistoID( ID.numeric() + 1 ); }
351  } else {
352  // use the title to create a unique literal ID
353  ID = HistoID( this->convertTitleToID( title ) );
354  // Just in case ...
355  while ( histoExists( ID ) ) { ID = HistoID( ID.idAsString() + "_" ); }
356  }
357 }
358 // ============================================================================
359 // Create an ID string from a title string
360 // ============================================================================
361 template <class PBASE>
363  // clean up the ID string for all unwanted characters
364  for ( const auto& i : m_idReplaceInfo ) { stringSearchReplace( title, i.first, i.second ); }
365  return title;
366 }
367 // get the constructed histogram path
368 // ============================================================================
369 template <class PBASE>
371  std::string path = histoTopDir() + histoDir();
372  return splitHistoDir() ? dirHbookName( path ) : path;
373 }
374 // ============================================================================
375 // 1D
378 // 2D
381 // 3D
384 // 1D Profile
387 // 2D Profile
390 // ============================================================================
391 // The END
392 // ============================================================================
393 #endif // GAUDIALG_GAUDIHISTOS_ICPP
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:34
GAUDI_API std::string htitle(const AIDA::IBaseHistogram *histo, const std::string &title="")
get the title
Definition: Fill.cpp:119
T empty(T... args)
std::string convertTitleToID(std::string title) const
Create an ID string from a title string.
GaudiAlg::ID HistoID
The actual type for histogram identifier.
Definition: HistoID.h:32
GAUDI_API std::string format(const AIDA::IHistogram1D *histo, const std::string &fmt)
Make the string representation of the histogram according to the specified format.
T endl(T... args)
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
Collection of useful utilities for manipulations with AIDA hisgograms.
Definition: Fill.h:36
T end(T... args)
few useful function to construct names of Hbook histograms and directories functions are imported fro...
void newHistoID(const std::string &title, HistoID &ID) const
Create a new histogram ID using the given title.
STL class.
GaudiKernel.
Definition: Fill.h:20
STL class.
std::string histoPath() const
get the constructed histogram path
GAUDI_API LiteralID idAsString() const
Return ID as string, for both numeric and literal IDs.
struct GAUDI_API map
Parametrisation class for map-like implementation.
AIDA::IHistogram1D * histo1D(const std::string &title) const
access the EXISTING 1D histogram by title return the pointer to existing 1D histogram or NULL
Definition: GaudiHistos.h:2280
bool noHistos() const
Check if all histogram maps are empty.
void monitorHisto(const AIDA::IBaseHistogram *hist, const HistoID &ID) const
Declare a histogram to the monitor service.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:61
AIDA::IProfile2D * profile2D(const double valueX, const double valueY, const double valueZ, const std::string &title, const double lowX, const double highX, const double lowY, const double highY, const unsigned long binsX=50, const unsigned long binsY=50, const double weight=1.0) const
fill the 2D profile histogram (book on demand)
T find_first_of(T... args)
const std::string & header() const
the table header
Simple class for the customizeble printout of the histogram tables.
collection of useful utilities to print certain objects (currently used for implementation in class G...
static std::string toString(const AIDA::IHistogram3D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:99
AIDA::IProfile1D * profile1D(const double valueX, const double valueY, const std::string &title, const double lowX, const double highX, const unsigned long binsX=100, const std::string &opt="", const double lowY=-std::numeric_limits< double >::max(), const double highY=std::numeric_limits< double >::max(), const double weight=1.0) const
fill the 1D profile histogram (book on demand)
AIDA::IHistogram2D * histo2D(const std::string &title) const
access the EXISTING 2D histogram by title return the pointer to existing 2D histogram or NULL
Definition: GaudiHistos.h:2297
std::string toString(const AIDA::IHistogram1D *histo) const
make the string representation according to the default format
T size(T... args)
AIDA::IHistogram3D * histo3D(const std::string &title) const
access the EXISTING 3D histogram by title return the pointer to existing 3D histogram or NULL
Definition: GaudiHistos.h:2305
T begin(T... args)
int printHistos(const MSG::Level level=MSG::ALWAYS) const
perform the actual printout of histograms
T substr(T... args)
static std::string toString(const AIDA::IHistogram2D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:85
bool numeric() const noexcept
Is this ID numeric.
Definition: GaudiHistoID.h:74
Templated base class providing common histogramming methods for GaudiAlgorithm and GaudiTool like cla...
Definition: GaudiHistos.h:65
bool isFailure() const
Definition: StatusCode.h:145
unsigned int totalNumberOfHistos() const
Returns the total number of histograms (of all types) currently booked.
KeyedObjectManager< map > Map
Forward declaration of specialized std::map-like object manager.
static std::string toString(const AIDA::IProfile2D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:128
ID class for Histogram and Ntuples.
Definition: GaudiHistoID.h:53
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202