Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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  class IBaseHistogram;
37  class IHistogram;
38  class IHistogram1D;
39  class IHistogram2D;
40  class IHistogram3D;
41  class IProfile;
42  class IProfile1D;
43  class IProfile2D;
44 } // namespace AIDA
45 // ============================================================================
46 // utility to allow iteration in order
47 // ============================================================================
48 namespace {
49  constexpr struct ordered_t {
50  template <typename C>
52  return {std::begin( c ), std::end( c )};
53  }
54  } ordered{};
55 
56  template <typename Map>
57  typename Map::mapped_type lookup_( const Map& map, const typename Map::key_type& ID ) {
58  auto found = map.find( ID );
59  return found != std::end( map ) ? found->second : nullptr;
60  }
61 
62  // ============================================================================
63  // Searches 'title' for all instances of 'A' and replaces them with 'B'
64  // ============================================================================
65  inline void stringSearchReplace( std::string& title, const std::string& A, const std::string& B ) {
66  for ( auto slash = title.find_first_of( A ); slash != std::string::npos; slash = title.find_first_of( A ) ) {
67  title = title.substr( 0, slash ) + B + title.substr( slash + A.size() );
68  }
69  }
70 } // namespace
71 // ============================================================================
72 // Initialise Histogramming
73 // ============================================================================
74 template <class PBASE>
76 #ifdef __ICC
77  i_ghInitialize
78 #else
79  initialize
80 #endif
81  () {
82  // initialize base class
83  const StatusCode sc = PBASE::initialize();
84  if ( sc.isFailure() ) return sc;
85 
86  // produce histograms?
87  if ( !produceHistos() ) {
88  this->debug() << "Histogram production is switched OFF" << endmsg;
89  return sc;
90  }
91 
92  // check the validity of histogram service
93  if ( !this->histoSvc() ) { return this->Error( "initialize():: IHistogramSvc* is invalid" ); }
94 
95  // Warn if the user has decided to use numerical automatic IDs
96  if ( useNumericAutoIDs() ) {
97  this->Warning(
98  "Using numerical automatic IDs. These are not guaranteed to be totally deterministic. Use with care...",
100  .ignore();
101  }
102 
103  // Finally, print the location histogram will be written to
104  this->Print( "The histogram path is set to be '" + histoPath() + "'", StatusCode( StatusCode::SUCCESS, true ),
105  MSG::DEBUG )
106  .ignore();
107 
108  return sc;
109 }
110 // ============================================================================
111 // Finalise Histogramming
112 // ============================================================================
113 template <class PBASE>
115 #ifdef __ICC
116  i_ghFinalize
117 #else
118  finalize
119 #endif
120  () {
121 
122  if ( produceHistos() ) {
123 
124  // Count how many histos of each type
125  if ( ( !noHistos() ) && histoCountersPrint() ) {
126  const unsigned int n1D = histo1DMapID().size();
127  const unsigned int n2D = histo2DMapID().size();
128  const unsigned int n3D = histo3DMapID().size();
129  const unsigned int n1DP = profile1DMapID().size();
130  const unsigned int n2DP = profile2DMapID().size();
131  const unsigned int total = n1D + n2D + n3D + n1DP + n2DP;
132  if ( total > 0 ) {
133  this->always() << "Booked " << total << " Histogram(s) : ";
134  if ( n1D > 0 ) this->always() << "1D=" << n1D << " ";
135  if ( n2D > 0 ) this->always() << "2D=" << n2D << " ";
136  if ( n3D > 0 ) this->always() << "3D=" << n3D << " ";
137  if ( n1DP > 0 ) this->always() << "1DProf=" << n1DP << " ";
138  if ( n2DP > 0 ) this->always() << "2DProf=" << n2DP << " ";
139  this->always() << endmsg;
140  }
141  }
142 
143  // detailed printing
144  if ( histosPrint() ) { printHistos(); }
145  }
146 
147  // clear all maps
148  m_histo1DMapTitle.clear();
149  m_histo2DMapTitle.clear();
150  m_histo3DMapTitle.clear();
151  m_histo1DMapID.clear();
152  m_histo2DMapID.clear();
153  m_histo3DMapID.clear();
154  m_profile1DMapTitle.clear();
155  m_profile2DMapTitle.clear();
156  m_profile1DMapID.clear();
157  m_profile2DMapID.clear();
158 
159  // finalize base class
160  return PBASE::finalize();
161 }
162 // ============================================================================
163 // perform the actual detailed printout of histograms
164 // ============================================================================
165 template <class PBASE>
167  using namespace Gaudi::Utils::Histos;
168 
169  if ( noHistos() ) {
170  if ( this->msgLevel( MSG::DEBUG ) ) { this->msgStream( level ) << "No histograms are booked" << endmsg; }
171  return 0; // RETURN
172  }
173 
174  MsgStream& msg = this->msgStream( level );
175 
176  // Printout all histograms
177 
178  if ( !histo1DMapID().empty() ) {
179  msg << "1D histograms in directory "
180  << "\"" << histoPath() << "\" : " << histo1DMapID().size();
181  const Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
182  if ( !table.header().empty() ) {
183  msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
184  }
185  for ( const auto& entry : ordered( histo1DMapID() ) ) {
186  const auto* aida = entry.second;
187  if ( !aida ) {
188  this->error() << "IHistogram1D points to NULL" << endmsg;
189  continue;
190  }
191  // format and print the row
192  msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
193  }
194  msg << endmsg;
195  }
196  // ==========================================================================
197  if ( !histo2DMapID().empty() ) {
198  msg << "2D histograms in directory "
199  << "\"" << histoPath() << "\" : " << histo2DMapID().size();
200 
201  for ( const auto& entry : ordered( histo2DMapID() ) ) {
202  const auto* aida = entry.second;
203  if ( !aida ) {
204  this->error() << "IHistogram2D points to NULL" << endmsg;
205  continue;
206  }
207  msg << std::endl << GaudiAlg::Print2D::toString( aida, entry.first );
208  }
209  msg << endmsg;
210  }
211  // ==========================================================================
212  if ( !histo3DMapID().empty() ) {
213  msg << "3D histograms in directory "
214  << "\"" << histoPath() << "\" : " << histo3DMapID().size();
215  for ( const auto& entry : ordered( histo3DMapID() ) ) {
216  const auto* aida = entry.second;
217  if ( !aida ) {
218  this->error() << "IHistogram3D points to NULL" << endmsg;
219  continue;
220  }
221  msg << std::endl << GaudiAlg::Print3D::toString( aida, entry.first );
222  }
223  msg << endmsg;
224  }
225  // ==========================================================================
226  if ( !profile1DMapID().empty() ) {
227  msg << "1D profile histograms in directory "
228  << "\"" << histoPath() << "\" : " << profile1DMapID().size();
229  const Gaudi::Utils::Histos::Table table( m_histo1DTableFormat, m_histo1DTableHeader );
230  if ( !table.header().empty() ) {
231  msg << std::endl << Gaudi::Utils::Histos::format( "ID", table.header(), m_histo1DTableFormatShort );
232  }
233  for ( const auto& entry : ordered( profile1DMapID() ) ) {
234  const auto* aida = entry.second;
235  if ( !aida ) {
236  this->error() << "IProfile1D points to NULL" << endmsg;
237  continue;
238  }
239  msg << std::endl << table.toString( aida, HistoID( entry.first ), m_histo1DTableFormatShort );
240  }
241  msg << endmsg;
242  }
243  // ==========================================================================
244  if ( !profile2DMapID().empty() ) {
245  msg << "2D profile histograms in directory "
246  << "\"" << histoPath() << "\" : " << profile2DMapID().size();
247  for ( const auto& entry : ordered( profile2DMapID() ) ) {
248  const auto* aida = entry.second;
249  if ( !aida ) {
250  this->error() << "IProfile2D points to NULL" << endmsg;
251  continue;
252  }
253  msg << std::endl << GaudiAlg::Print2DProf::toString( aida, entry.first );
254  }
255  msg << endmsg;
256  }
257  //
258  return this->totalNumberOfHistos();
259 }
260 // ============================================================================
261 // Check if all histogram maps are empty
262 // ============================================================================
263 template <class PBASE>
265  return ( histo1DMapTitle().empty() && histo2DMapTitle().empty() && histo3DMapTitle().empty() &&
266  profile1DMapTitle().empty() && profile2DMapTitle().empty() && histo1DMapID().empty() &&
267  histo2DMapID().empty() && histo3DMapID().empty() && profile1DMapID().empty() && profile2DMapID().empty() );
268 }
269 // ============================================================================
270 // Declare a histogram to the monitor service
271 // ============================================================================
272 template <class PBASE>
273 void GaudiHistos<PBASE>::monitorHisto( const AIDA::IBaseHistogram* hist, const HistoID& ID ) const {
274  if ( hist && m_declareMoniHists ) {
275  if ( this->msgLevel( MSG::DEBUG ) ) {
276  this->debug() << "Monitoring histogram '" << ID.idAsString() << "' desc = '"
277  << Gaudi::Utils::Histos::htitle( hist ) << "'" << endmsg;
278  }
279  this->declareInfo( histoPath() + "/" + ID.idAsString(), hist, Gaudi::Utils::Histos::htitle( hist ) );
280  }
281 }
282 // ============================================================================
283 // access the EXISTING 1D histogram by ID
284 // ============================================================================
285 template <class PBASE>
286 AIDA::IHistogram1D* GaudiHistos<PBASE>::histo1D( const HistoID& ID ) const {
287  return lookup_( histo1DMapID(), ID );
288 }
289 // ============================================================================
290 // access the EXISTING 2D histogram by ID
291 // ============================================================================
292 template <class PBASE>
293 AIDA::IHistogram2D* GaudiHistos<PBASE>::histo2D( const HistoID& ID ) const {
294  return lookup_( histo2DMapID(), ID );
295 }
296 // ============================================================================
297 // access the EXISTING 3D histogram by ID
298 // ============================================================================
299 template <class PBASE>
300 AIDA::IHistogram3D* GaudiHistos<PBASE>::histo3D( const HistoID& ID ) const {
301  return lookup_( histo3DMapID(), ID );
302 }
303 // ============================================================================
304 // access the EXISTING 1D profile histogram by ID
305 // ============================================================================
306 template <class PBASE>
307 AIDA::IProfile1D* GaudiHistos<PBASE>::profile1D( const HistoID& ID ) const {
308  return lookup_( profile1DMapID(), ID );
309 }
310 // ============================================================================
311 // access the EXISTING 2D profile histogram by ID
312 // ============================================================================
313 template <class PBASE>
314 AIDA::IProfile2D* GaudiHistos<PBASE>::profile2D( const HistoID& ID ) const {
315  return lookup_( profile2DMapID(), ID );
316 }
317 // ============================================================================
318 // Returns the total number of histograms (of all types) currently booked
319 // ============================================================================
320 template <class PBASE>
322  return histo1DMapID().size() + histo2DMapID().size() + histo3DMapID().size() + profile1DMapID().size() +
323  profile2DMapID().size();
324 }
325 // ============================================================================
326 // Create a new histogram ID using the given title
327 // ============================================================================
328 template <class PBASE>
329 void GaudiHistos<PBASE>::newHistoID( const std::string& title, HistoID& ID ) const {
330  if ( useNumericAutoIDs() || title.empty() ) {
331  if ( !useNumericAutoIDs() ) {
332  this->Warning(
333  "Cannot generate automatic literal ID from an empty title ! Using numeric ID instead for histogram ID",
335  .ignore();
336  }
337  // propose the histogram ID (always numeric)
338  ID = HistoID( totalNumberOfHistos() + 1 + histoOffSet() );
339  // adjust the proposed ID
340  while ( histoExists( ID ) ) { ID = HistoID( ID.numeric() + 1 ); }
341  } else {
342  // use the title to create a unique literal ID
343  ID = HistoID( this->convertTitleToID( title ) );
344  // Just in case ...
345  while ( histoExists( ID ) ) { ID = HistoID( ID.idAsString() + "_" ); }
346  }
347 }
348 // ============================================================================
349 // Create an ID string from a title string
350 // ============================================================================
351 template <class PBASE>
353  // clean up the ID string for all unwanted characters
354  for ( const auto& i : m_idReplaceInfo ) { stringSearchReplace( title, i.first, i.second ); }
355  return title;
356 }
357 // get the constructed histogram path
358 // ============================================================================
359 template <class PBASE>
361  std::string path = histoTopDir() + histoDir();
362  return splitHistoDir() ? dirHbookName( path ) : path;
363 }
364 // ============================================================================
365 // 1D
368 // 2D
371 // 3D
374 // 1D Profile
377 // 2D Profile
380 // ============================================================================
381 // The END
382 // ============================================================================
383 #endif // GAUDIALG_GAUDIHISTOS_ICPP
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:109
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:2287
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:22
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 histogram according to the specified format.
T endl(T...args)
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
Collection of useful utilities for manipulations with AIDA hisgograms.
Definition: Fill.h:26
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:130
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:2270
struct GAUDI_API map
Parametrisation class for map-like implementation.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
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:89
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:64
T substr(T...args)
static std::string toString(const AIDA::IHistogram2D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:75
Templated base class providing common histogramming methods for GaudiAlgorithm and GaudiTool like cla...
Definition: GaudiHistos.h:55
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:118
ID class for Histogram and Ntuples.
Definition: GaudiHistoID.h:43
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:2295
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
std::string toString(const AIDA::IHistogram1D *histo) const
make the string representation according to the default format