The Gaudi Framework  v30r3 (a5ef0a68)
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 // Constructor initialisation and job options
78 // =============================================================================
79 template <class PBASE>
81 {
82  m_histosPrint.declareUpdateHandler( &GaudiHistos<PBASE>::printHistoHandler, this );
83 }
84 // ============================================================================
85 // Initialise Histogramming
86 // ============================================================================
87 template <class PBASE>
89 #ifdef __ICC
90  i_ghInitialize
91 #else
92  initialize
93 #endif
94  ()
95 {
96  // initialize base class
97  const StatusCode sc = PBASE::initialize();
98  if ( sc.isFailure() ) return sc;
99 
100  // produce histograms?
101  if ( !produceHistos() ) {
102  this->debug() << "Histogram production is switched OFF" << endmsg;
103  return sc;
104  }
105 
106  // check the validity of histogram service
107  if ( !this->histoSvc() ) {
108  return this->Error( "initialize():: IHistogramSvc* is invalid" );
109  }
110 
111  // Warn if the user has decided to use numerical automatic IDs
112  if ( useNumericAutoIDs() ) {
113  this->Warning(
114  "Using numerical automatic IDs. These are not guaranteed to be totally deterministic. Use with care...",
116  .ignore();
117  }
118 
119  // Finally, print the location histogram will be written to
120  this->Print( "The histogram path is set to be '" + histoPath() + "'", StatusCode( StatusCode::SUCCESS, true ),
121  MSG::DEBUG )
122  .ignore();
123 
124  return sc;
125 }
126 // ============================================================================
127 // Finalise Histogramming
128 // ============================================================================
129 template <class PBASE>
131 #ifdef __ICC
132  i_ghFinalize
133 #else
134  finalize
135 #endif
136  ()
137 {
138 
139  if ( produceHistos() ) {
140 
141  // Count how many histos of each type
142  if ( ( !noHistos() ) && histoCountersPrint() ) {
143  const unsigned int n1D = histo1DMapID().size();
144  const unsigned int n2D = histo2DMapID().size();
145  const unsigned int n3D = histo3DMapID().size();
146  const unsigned int n1DP = profile1DMapID().size();
147  const unsigned int n2DP = profile2DMapID().size();
148  const unsigned int total = n1D + n2D + n3D + n1DP + n2DP;
149  if ( total > 0 ) {
150  this->always() << "Booked " << total << " Histogram(s) : ";
151  if ( n1D > 0 ) this->always() << "1D=" << n1D << " ";
152  if ( n2D > 0 ) this->always() << "2D=" << n2D << " ";
153  if ( n3D > 0 ) this->always() << "3D=" << n3D << " ";
154  if ( n1DP > 0 ) this->always() << "1DProf=" << n1DP << " ";
155  if ( n2DP > 0 ) this->always() << "2DProf=" << n2DP << " ";
156  this->always() << endmsg;
157  }
158  }
159 
160  // detailed printing
161  if ( histosPrint() ) {
162  printHistos();
163  }
164  }
165 
166  // clear all maps
167  m_histo1DMapTitle.clear();
168  m_histo2DMapTitle.clear();
169  m_histo3DMapTitle.clear();
170  m_histo1DMapID.clear();
171  m_histo2DMapID.clear();
172  m_histo3DMapID.clear();
173  m_profile1DMapTitle.clear();
174  m_profile2DMapTitle.clear();
175  m_profile1DMapID.clear();
176  m_profile2DMapID.clear();
177 
178  // finalize base class
179  return PBASE::finalize();
180 }
181 // ============================================================================
182 // perform the actual detailed printout of histograms
183 // ============================================================================
184 template <class PBASE>
186 {
187  using namespace Gaudi::Utils::Histos;
188 
189  if ( noHistos() ) {
190  if ( this->msgLevel( MSG::DEBUG ) ) {
191  this->msgStream( level ) << "No histograms are booked" << endmsg;
192  }
193  return 0; // RETURN
194  }
195 
196  MsgStream& msg = this->msgStream( level );
197 
198  // Printout all histograms
199 
200  Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
201 
202  if ( !histo1DMapID().empty() ) {
203  msg << "List of booked 1D histograms in directory "
204  << "\"" << histoPath() << "\" :-";
205 
206  if ( !table.header().empty() ) {
207  msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
208  }
209  for ( const auto& entry : ordered( histo1DMapID() ) ) {
210  const auto* aida = entry.second;
211  if ( !aida ) {
212  this->error() << "IHistogram1D points to NULL" << endmsg;
213  continue;
214  }
215  // format and print the row
216  msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
217  }
218  msg << endmsg;
219  }
220  // ==========================================================================
221  if ( !histo2DMapID().empty() ) {
222  msg << "List of booked 2D histograms in directory "
223  << "\"" << histoPath() << "\" :-";
224 
225  for ( const auto& entry : ordered( histo2DMapID() ) ) {
226  const auto* aida = entry.second;
227  if ( !aida ) {
228  this->error() << "IHistogram2D points to NULL" << endmsg;
229  continue;
230  }
231  msg << std::endl << GaudiAlg::Print2D::toString( aida, entry.first );
232  }
233  msg << endmsg;
234  }
235  // ==========================================================================
236  if ( !histo3DMapID().empty() ) {
237  msg << "List of booked 3D histograms in directory "
238  << "\"" << histoPath() << "\" :-";
239  for ( const auto& entry : ordered( histo3DMapID() ) ) {
240  const auto* aida = entry.second;
241  if ( !aida ) {
242  this->error() << "IHistogram3D points to NULL" << endmsg;
243  continue;
244  }
245  msg << std::endl << GaudiAlg::Print3D::toString( aida, entry.first );
246  }
247  msg << endmsg;
248  }
249  // ==========================================================================
250  if ( !profile1DMapID().empty() ) {
251  msg << "List of booked 1D profile histograms in directory "
252  << "\"" << histoPath() << "\" :-";
253  for ( const auto& entry : ordered( profile1DMapID() ) ) {
254  const auto* aida = entry.second;
255  if ( !aida ) {
256  this->error() << "IProfile1D points to NULL" << endmsg;
257  continue;
258  }
259  msg << std::endl << GaudiAlg::Print1DProf::toString( aida, entry.first );
260  }
261  msg << endmsg;
262  }
263  // ==========================================================================
264  if ( !profile2DMapID().empty() ) {
265  msg << "List of booked 2D profile histograms in directory "
266  << "\"" << histoPath() << "\" :-";
267  for ( const auto& entry : ordered( profile2DMapID() ) ) {
268  const auto* aida = entry.second;
269  if ( !aida ) {
270  this->error() << "IProfile2D points to NULL" << endmsg;
271  continue;
272  }
273  msg << std::endl << GaudiAlg::Print2DProf::toString( aida, entry.first );
274  }
275  msg << endmsg;
276  }
277  //
278  return this->totalNumberOfHistos();
279 }
280 // ============================================================================
281 // Check if all histogram maps are empty
282 // ============================================================================
283 template <class PBASE>
285 {
286  return ( histo1DMapTitle().empty() && histo2DMapTitle().empty() && histo3DMapTitle().empty() &&
287  profile1DMapTitle().empty() && profile2DMapTitle().empty() && histo1DMapID().empty() &&
288  histo2DMapID().empty() && histo3DMapID().empty() && profile1DMapID().empty() && profile2DMapID().empty() );
289 }
290 // ============================================================================
291 // Declare a histogram to the monitor service
292 // ============================================================================
293 template <class PBASE>
294 void GaudiHistos<PBASE>::monitorHisto( const AIDA::IBaseHistogram* hist, const HistoID& ID ) const
295 {
296  if ( hist && m_declareMoniHists ) {
297  if ( this->msgLevel( MSG::DEBUG ) ) {
298  this->debug() << "Monitoring histogram '" << ID.idAsString() << "' desc = '"
299  << Gaudi::Utils::Histos::htitle( hist ) << "'" << endmsg;
300  }
301  this->declareInfo( histoPath() + "/" + ID.idAsString(), hist, Gaudi::Utils::Histos::htitle( hist ) );
302  }
303 }
304 // ============================================================================
305 // access the EXISTING 1D histogram by ID
306 // ============================================================================
307 template <class PBASE>
308 AIDA::IHistogram1D* GaudiHistos<PBASE>::histo1D( const HistoID& ID ) const
309 {
310  return lookup_( histo1DMapID(), ID );
311 }
312 // ============================================================================
313 // access the EXISTING 2D histogram by ID
314 // ============================================================================
315 template <class PBASE>
316 AIDA::IHistogram2D* GaudiHistos<PBASE>::histo2D( const HistoID& ID ) const
317 {
318  return lookup_( histo2DMapID(), ID );
319 }
320 // ============================================================================
321 // access the EXISTING 3D histogram by ID
322 // ============================================================================
323 template <class PBASE>
324 AIDA::IHistogram3D* GaudiHistos<PBASE>::histo3D( const HistoID& ID ) const
325 {
326  return lookup_( histo3DMapID(), ID );
327 }
328 // ============================================================================
329 // access the EXISTING 1D profile histogram by ID
330 // ============================================================================
331 template <class PBASE>
332 AIDA::IProfile1D* GaudiHistos<PBASE>::profile1D( const HistoID& ID ) const
333 {
334  return lookup_( profile1DMapID(), ID );
335 }
336 // ============================================================================
337 // access the EXISTING 2D profile histogram by ID
338 // ============================================================================
339 template <class PBASE>
340 AIDA::IProfile2D* GaudiHistos<PBASE>::profile2D( const HistoID& ID ) const
341 {
342  return lookup_( profile2DMapID(), ID );
343 }
344 // ============================================================================
345 // Returns the total number of histograms (of all types) currently booked
346 // ============================================================================
347 template <class PBASE>
349 {
350  return histo1DMapID().size() + histo2DMapID().size() + histo3DMapID().size() + profile1DMapID().size() +
351  profile2DMapID().size();
352 }
353 // ============================================================================
354 // Create a new histogram ID using the given title
355 // ============================================================================
356 template <class PBASE>
357 void GaudiHistos<PBASE>::newHistoID( const std::string& title, HistoID& ID ) const
358 {
359  if ( useNumericAutoIDs() || title.empty() ) {
360  if ( !useNumericAutoIDs() ) {
361  this->Warning(
362  "Cannot generate automatic literal ID from an empty title ! Using numeric ID instead for histogram ID",
364  .ignore();
365  }
366  // propose the histogram ID (always numeric)
367  ID = HistoID( totalNumberOfHistos() + 1 + histoOffSet() );
368  // adjust the proposed ID
369  while ( histoExists( ID ) ) {
370  ID = HistoID( ID.numeric() + 1 );
371  }
372  } else {
373  // use the title to create a unique literal ID
374  ID = HistoID( this->convertTitleToID( title ) );
375  // Just in case ...
376  while ( histoExists( ID ) ) {
377  ID = HistoID( ID.idAsString() + "_" );
378  }
379  }
380 }
381 // ============================================================================
382 // Create an ID string from a title string
383 // ============================================================================
384 template <class PBASE>
386 {
387  // clean up the ID string for all unwanted characters
388  for ( const auto& i : m_idReplaceInfo ) {
389  stringSearchReplace( title, i.first, i.second );
390  }
391  return title;
392 }
393 // ============================================================================
394 // the handler for "HistoPrint" property
395 // ============================================================================
396 template <class PBASE>
398 {
399  // no action if not yet initialized
400  if ( this->FSMState() < Gaudi::StateMachine::INITIALIZED ) {
401  return;
402  }
403  if ( this->histosPrint() ) {
404  this->printHistos( MSG::ALWAYS );
405  }
406 }
407 // ============================================================================
408 // get the constructed histogram path
409 // ============================================================================
410 template <class PBASE>
412 {
413  std::string path = histoTopDir() + histoDir();
414  return splitHistoDir() ? dirHbookName( path ) : path;
415 }
416 // ============================================================================
417 // 1D
420 // 2D
423 // 3D
426 // 1D Profile
429 // 2D Profile
432 // ============================================================================
433 // The END
434 // ============================================================================
435 #endif // GAUDIALG_GAUDIHISTOS_ICPP
436 // ============================================================================
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
void printHistoHandler(Gaudi::Details::PropertyBase &)
the handler for "HistoPrint" property
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
PropertyBase base class allowing PropertyBase* collections to be "homogeneous".
Definition: Property.h:32
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
void initGaudiHistosConstructor()
Constructor initialisation and job options.