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