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 <string>
17 #include <vector>
18 #include <set>
19 #include <cmath>
20 // ============================================================================
21 #include "boost/algorithm/string/replace.hpp"
22 // ============================================================================
23 // GaudiKernel
24 // ============================================================================
25 #include "GaudiKernel/MsgStream.h"
27 // ============================================================================
28 // GaudiUtils
29 // ============================================================================
31 // ============================================================================
32 // GaudiAlg
33 // ============================================================================
34 #include "GaudiAlg/GaudiHistos.h"
35 #include "GaudiAlg/Print.h"
36 #include "GaudiAlg/Fill.h"
37 #include "GaudiAlg/HbookName.h"
38 // ============================================================================
39 // forward declarations from AIDA
40 // ============================================================================
41 namespace AIDA
42 {
43  class IBaseHistogram ;
44  class IHistogram ;
45  class IHistogram1D ;
46  class IHistogram2D ;
47  class IHistogram3D ;
48  class IProfile ;
49  class IProfile1D ;
50  class IProfile2D ;
51 }
52 // ============================================================================
53 // utility to allow iteration in order
54 // ============================================================================
55 namespace {
56  constexpr struct ordered_t {
57  template <typename C>
59  return { std::begin(c), std::end(c) };
60  }
61  } ordered {};
62 
63  template <typename Map>
64  typename Map::mapped_type lookup_(const Map& map, const typename Map::key_type& ID) {
65  auto found = map.find( ID ) ;
66  return found != std::end(map) ? found->second : nullptr;
67  }
68 
69  // ============================================================================
70  // Searches 'title' for all instancies of 'A' and replaces them with 'B'
71  // ============================================================================
72  inline void stringSearchReplace ( std::string & title ,
73  const std::string & A ,
74  const std::string & B )
75  {
76  for ( auto slash = title.find_first_of ( A ) ;
77  slash != std::string::npos ;
78  slash = title.find_first_of( A ) )
79  {
80  title = title.substr(0,slash) + B + title.substr(slash+A.size());
81  }
82  }
83 }
84 // =============================================================================
85 // Constructor initialisation and job options
86 // =============================================================================
87 template <class PBASE>
89 {
90  // SWITCH ON/OFF the histograms
91  this->declareProperty
92  ( "HistoProduce" ,
93  m_produceHistos = true ,
94  "Switch on/off the production of histograms" ) ;
95  // print the histograms at finalization
96  this->declareProperty
97  ( "HistoPrint" ,
98  m_histosPrint = false ,
99  "Switch on/off the printout of histograms at finalization" )
100  -> declareUpdateHandler ( &GaudiHistos<PBASE>::printHistoHandler, this ) ;
101  this->declareProperty
102  ( "HistoCountersPrint" ,
103  m_histoCountersPrint = true ,
104  "Switch on/off the printout of histogram counters at finalization" ) ;
105  // check for NaN/Finite
106  this->declareProperty
107  ( "HistoCheckForNaN" ,
108  m_checkForNaN = true ,
109  "Switch on/off the checks for NaN and Infinity for histogram fill" ) ;
110  // for HBOOK persistency, 'true' can be useful
111  this->declareProperty
112  ( "HistoSplitDir" ,
113  m_splitHistoDir = false ,
114  "Split long directory names into short pieces (suitable for HBOOK)" );
115  // general OffSet for histogram ID
116  this->declareProperty
117  ( "HistoOffSet" ,
118  m_histoOffSet = 0 ,
119  "OffSet for automatically assigned histogram numerical identifiers " ) ;
120  // top level histogram directory
121  this->declareProperty
122  ( "HistoTopDir" ,
123  m_histoTopDir = "" ,
124  "Top level histogram directory (take care that it ends with '/')" ) ;
125  // histogram directory
126  this->declareProperty
127  ( "HistoDir" ,
128  m_histoDir = boost::algorithm::replace_all_copy( this->name(), ":", "_" ) ,
129  "Histogram Directory" ) ;
130  // control output level of histograms
131  this->declareProperty ( "FullDetail" , m_fullDetail = false ) ;
132  // monitor histograms
133  this->declareProperty ( "MonitorHistograms" , m_declareMoniHists = true ) ;
134  // format for 1D-histograms printout
135  this->declareProperty
136  ( "FormatFor1DHistoTable" ,
137  m_histo1DTableFormat = Gaudi::Utils::Histos::Formats::format () ,
138  "Format string for printout of 1D histograms" ) ;
139  // "short" format for 1D-histograms printout
140  this->declareProperty
141  ( "ShortFormatFor1DHistoTable" ,
142  m_histo1DTableFormatShort = " | %1$-25.25s %2%" ,
143  "Format string for printout of 1D histograms" ) ;
144  // the header for 1D-histogram table
145  this->declareProperty
146  ( "HeaderFor1DHistoTable" ,
147  m_histo1DTableHeader = Gaudi::Utils::Histos::Formats::header () ,
148  "The table header for printout of 1D histograms " ) ;
149  this->declareProperty
150  ( "UseSequencialNumericAutoIDs", m_useNumericAutoIDs = false,
151  "Flag to allow users to switch back to the old style of creating numerical automatic IDs" );
152  this->declareProperty
153  ( "AutoStringIDPurgeMap", m_idReplaceInfo = { { "/", "=SLASH=" } } ,
154  "Map of strings to search and replace when using the title as the basis of automatically generated literal IDs" );
155 }
156 // ============================================================================
157 // Initialise Histogramming
158 // ============================================================================
159 template <class PBASE>
161 #ifdef __ICC
162 i_ghInitialize
163 #else
165 #endif
166 ()
167 {
168  // initialize base class
169  const StatusCode sc = PBASE::initialize();
170  if ( sc.isFailure() ) return sc;
171 
172  // produce histograms?
173  if ( !produceHistos() )
174  {
175  this->debug() << "Histogram production is switched OFF" << endmsg;
176  return sc;
177  }
178 
179  // check the validity of histogram service
180  if ( !this->histoSvc() )
181  { return this->Error("initialize():: IHistogramSvc* is invalid"); }
182 
183  // Warn if the user has decided to use numerical automatic IDs
184  if ( useNumericAutoIDs() )
185  {
186  this ->
187  Warning( "Using numerical automatic IDs. These are not guaranteed to be totally deterministic. Use with care...",
188  StatusCode::SUCCESS ).ignore();
189  }
190 
191  // Finally, print the location histogram will be written to
192  this->Print
193  ( "The histogram path is set to be '" + histoPath() + "'",
194  StatusCode( StatusCode::SUCCESS, true ) , MSG::DEBUG ).ignore();
195 
196  return sc;
197 }
198 // ============================================================================
199 // Finalise Histogramming
200 // ============================================================================
201 template <class PBASE>
203 #ifdef __ICC
204 i_ghFinalize
205 #else
206 finalize
207 #endif
208 ()
209 {
210 
211  if ( produceHistos() )
212  {
213 
214  // Count how many histos of each type
215  if ( (!noHistos()) && histoCountersPrint() )
216  {
217  const unsigned int n1D = histo1DMapID () . size () ;
218  const unsigned int n2D = histo2DMapID () . size () ;
219  const unsigned int n3D = histo3DMapID () . size () ;
220  const unsigned int n1DP = profile1DMapID () . size () ;
221  const unsigned int n2DP = profile2DMapID () . size () ;
222  const unsigned int total = n1D+n2D+n3D+n1DP+n2DP;
223  if ( total>0 )
224  {
225  this->always() << "Booked " << total << " Histogram(s) : ";
226  if ( n1D>0 ) this->always() << "1D=" << n1D << " ";
227  if ( n2D>0 ) this->always() << "2D=" << n2D << " ";
228  if ( n3D>0 ) this->always() << "3D=" << n3D << " ";
229  if ( n1DP>0 ) this->always() << "1DProf=" << n1DP << " ";
230  if ( n2DP>0 ) this->always() << "2DProf=" << n2DP << " ";
231  this->always() << endmsg;
232  }
233  }
234 
235  // detailed printing
236  if ( histosPrint() ) { printHistos() ; }
237 
238  }
239 
240  // clear all maps
241  m_histo1DMapTitle . clear () ;
242  m_histo2DMapTitle . clear () ;
243  m_histo3DMapTitle . clear () ;
244  m_histo1DMapID . clear () ;
245  m_histo2DMapID . clear () ;
246  m_histo3DMapID . clear () ;
247  m_profile1DMapTitle . clear () ;
248  m_profile2DMapTitle . clear () ;
249  m_profile1DMapID . clear () ;
250  m_profile2DMapID . clear () ;
251 
252  // finalize base class
253  return PBASE::finalize();
254 }
255 // ============================================================================
256 // perform the actual detailed printout of histograms
257 // ============================================================================
258 template <class PBASE>
260 {
261  using namespace Gaudi::Utils::Histos ;
262 
263  if ( noHistos() )
264  {
265  if ( this->msgLevel(MSG::DEBUG) )
266  { this->msgStream(level) << "No histograms are booked" << endmsg ; }
267  return 0 ; // RETURN
268  }
269 
270  MsgStream & msg = this->msgStream(level);
271 
272  // Printout all histograms
273 
275  ( m_histo1DTableFormat ,
276  m_histo1DTableHeader ) ;
277 
278  if ( !histo1DMapID().empty() )
279  {
280  msg << "List of booked 1D histograms in directory "
281  << "\"" << histoPath() << "\" :-" ;
282 
283  if ( !table.header().empty() )
284  {
286  ( "ID" , table.header() , m_histo1DTableFormatShort ) ;
287  }
288  for ( const auto& entry : ordered( histo1DMapID() ))
289  {
290  const auto* aida = entry.second ;
291  if ( !aida )
292  { this->error() << "IHistogram1D points to NULL" << endmsg ; continue ; }
293  // format and print the row
294  msg << std::endl << table.toString
295  ( aida ,
296  HistoID ( entry.first ) ,
297  m_histo1DTableFormatShort ) ;
298  }
299  msg << endmsg ;
300  }
301  // ==========================================================================
302  if ( !histo2DMapID().empty() )
303  {
304  msg << "List of booked 2D histograms in directory "
305  << "\"" << histoPath() << "\" :-" ;
306 
307  for ( const auto& entry : ordered( histo2DMapID() ) )
308  {
309  const auto* aida = entry.second ;
310  if ( !aida )
311  { this->error() << "IHistogram2D points to NULL" << endmsg ; continue ; }
312  msg << std::endl
313  << GaudiAlg::Print2D::toString ( aida , entry.first );
314  }
315  msg << endmsg ;
316  }
317  // ==========================================================================
318  if ( !histo3DMapID().empty() )
319  {
320  msg << "List of booked 3D histograms in directory "
321  << "\"" << histoPath() << "\" :-" ;
322  for ( const auto& entry : ordered( histo3DMapID() ) )
323  {
324  const auto* aida = entry.second ;
325  if ( !aida )
326  { this->error() << "IHistogram3D points to NULL" << endmsg ; continue ; }
327  msg << std::endl << GaudiAlg::Print3D::toString ( aida , entry.first );
328  }
329  msg << endmsg ;
330  }
331  // ==========================================================================
332  if ( !profile1DMapID().empty() )
333  {
334  msg << "List of booked 1D profile histograms in directory "
335  << "\"" << histoPath() << "\" :-" ;
336  for ( const auto& entry : ordered( profile1DMapID() ) )
337  {
338  const auto* aida = entry.second ;
339  if ( !aida )
340  { this->error() << "IProfile1D points to NULL" << endmsg ; continue ; }
341  msg << std::endl << GaudiAlg::Print1DProf::toString ( aida , entry.first );
342  }
343  msg << endmsg ;
344  }
345  // ==========================================================================
346  if ( !profile2DMapID().empty() )
347  {
348  msg << "List of booked 2D profile histograms in directory "
349  << "\"" << histoPath() << "\" :-" ;
350  for ( const auto& entry : ordered(profile2DMapID() ) )
351  {
352  const auto* aida = entry.second ;
353  if ( !aida )
354  { this->error() << "IProfile2D points to NULL" << endmsg ; continue ; }
355  msg << std::endl << GaudiAlg::Print2DProf::toString ( aida , entry.first );
356  }
357  msg << endmsg ;
358  }
359  //
360  return this->totalNumberOfHistos() ;
361 }
362 // ============================================================================
363 // Check if all histogram maps are empty
364 // ============================================================================
365 template <class PBASE>
367 {
368  return ( histo1DMapTitle () . empty() &&
369  histo2DMapTitle () . empty() &&
370  histo3DMapTitle () . empty() &&
371  profile1DMapTitle () . empty() &&
372  profile2DMapTitle () . empty() &&
373  histo1DMapID () . empty() &&
374  histo2DMapID () . empty() &&
375  histo3DMapID () . empty() &&
376  profile1DMapID () . empty() &&
377  profile2DMapID () . empty() );
378 }
379 // ============================================================================
380 // Declare a histogram to the monitor service
381 // ============================================================================
382 template <class PBASE>
384 ( const AIDA::IBaseHistogram* hist,
385  const HistoID& ID ) const
386 {
387  if ( hist && m_declareMoniHists )
388  {
389  if ( this->msgLevel(MSG::DEBUG) )
390  {
391  this->debug() << "Monitoring histogram '"
392  << ID.idAsString() << "' desc = '"
393  << Gaudi::Utils::Histos::htitle(hist) << "'" << endmsg;
394  }
395  this->declareInfo ( histoPath()+"/"+ID.idAsString() ,
396  hist ,
398  }
399 }
400 // ============================================================================
401 // access the EXISTING 1D histogram by ID
402 // ============================================================================
403 template <class PBASE>
404 AIDA::IHistogram1D* GaudiHistos<PBASE>::histo1D ( const HistoID& ID ) const
405 {
406  return lookup_( histo1DMapID(), ID );
407 }
408 // ============================================================================
409 // access the EXISTING 2D histogram by ID
410 // ============================================================================
411 template <class PBASE>
412 AIDA::IHistogram2D* GaudiHistos<PBASE>::histo2D ( const HistoID& ID ) const
413 {
414  return lookup_( histo2DMapID(), ID );
415 }
416 // ============================================================================
417 // access the EXISTING 3D histogram by ID
418 // ============================================================================
419 template <class PBASE>
420 AIDA::IHistogram3D* GaudiHistos<PBASE>::histo3D ( const HistoID& ID ) const
421 {
422  return lookup_( histo3DMapID(), ID );
423 }
424 // ============================================================================
425 // access the EXISTING 1D profile histogram by ID
426 // ============================================================================
427 template <class PBASE>
428 AIDA::IProfile1D* GaudiHistos<PBASE>::profile1D ( const HistoID& ID ) const
429 {
430  return lookup_( profile1DMapID(), ID );
431 }
432 // ============================================================================
433 // access the EXISTING 2D profile histogram by ID
434 // ============================================================================
435 template <class PBASE>
436 AIDA::IProfile2D* GaudiHistos<PBASE>::profile2D ( const HistoID& ID ) const
437 {
438  return lookup_( profile2DMapID(), ID );
439 }
440 // ============================================================================
441 // Returns the total number of histograms (of all types) currently booked
442 // ============================================================================
443 template <class PBASE>
445 {
446  return
447  histo1DMapID () . size () +
448  histo2DMapID () . size () +
449  histo3DMapID () . size () +
450  profile1DMapID () . size () +
451  profile2DMapID () . size () ;
452 }
453 // ============================================================================
454 // Create a new histogram ID using the given title
455 // ============================================================================
456 template <class PBASE>
458 ( const std::string & title ,
459  HistoID& ID ) const
460 {
461  if ( useNumericAutoIDs() || title.empty() )
462  {
463  if ( !useNumericAutoIDs() )
464  {
465  this -> Warning( "Cannot generate automatic literal ID from an empty title ! Using numeric ID instead for histogram ID",
467  }
468  // propose the histogram ID (always numeric)
469  ID = HistoID( totalNumberOfHistos() + 1 + histoOffSet() );
470  // adjust the proposed ID
471  while ( histoExists( ID ) ) { ID = HistoID ( ID.numeric() + 1 ) ; }
472  }
473  else
474  {
475  // use the title to create a unique literal ID
476  ID = HistoID( this->convertTitleToID(title) );
477  // Just in case ...
478  while ( histoExists( ID ) ) { ID = HistoID(ID.idAsString()+"_"); }
479  }
480 }
481 // ============================================================================
482 // Create an ID string from a title string
483 // ============================================================================
484 template <class PBASE>
486 {
487  // clean up the ID string for all unwanted characters
488  for ( const auto& i : m_idReplaceInfo )
489  {
490  stringSearchReplace( title, i.first, i.second );
491  }
492  return title;
493 }
494 // ============================================================================
495 // the handler for "HistoPrint" property
496 // ============================================================================
497 template < class PBASE >
499 {
500  // no action if not yet initialized
501  if ( this -> FSMState() < Gaudi::StateMachine::INITIALIZED ) { return ; }
502  if ( this -> histosPrint() ) { this -> printHistos ( MSG::ALWAYS ) ; }
503 }
504 // ============================================================================
505 // get the constructed histogram path
506 // ============================================================================
507 template < class PBASE >
509 {
510  std::string path = histoTopDir() + histoDir();
511  return splitHistoDir() ? dirHbookName(path) : path;
512 }
513 // ============================================================================
514 // 1D
517 // 2D
520 // 3D
523 // 1D Profile
526 // 2D Profile
529 // ============================================================================
530 // The END
531 // ============================================================================
532 #endif // GAUDIALG_GAUDIHISTOS_ICPP
533 // ============================================================================
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:138
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:2590
int printHistos(const MSG::Level level=MSG::ALWAYS) const
perform the actual printout of histograms
def initialize()
Definition: AnalysisTest.py:12
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)
void printHistoHandler(Property &)
the handler for "HistoPrint" property
bool noHistos() const
Check if all histogram maps are empty.
GaudiAlg::ID HistoID
The actual type for histogram identifier.
Definition: HistoID.h:23
tuple c
Definition: gaudirun.py:391
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:27
T end(T...args)
few useful function to construct names of Hbook histograms and directories functions are imported fro...
STL class.
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
GAUDI_API std::string header(const int ID=Default)
get the recommended header by enum
GaudiKernel.
Definition: Fill.h:8
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:2569
struct GAUDI_API map
Parametrisation class for map-like implementation.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
GAUDI_API std::string format(const int ID=Default)
get the format by enum
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:107
GAUDI_API std::string path(const AIDA::IBaseHistogram *aida)
get the path in THS for AIDA histogram
std::string histoPath() const
get the constructed histogram path
T size(T...args)
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
T begin(T...args)
GAUDI_API LiteralID idAsString() const
Return ID as string, for both numeric and literal IDs.
T substr(T...args)
static std::string toString(const AIDA::IHistogram2D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:87
Templated base class providing common histogramming methods for GaudiAlgorithm and GaudiTool like cla...
Definition: GaudiHistos.h:48
static std::string toString(const AIDA::IProfile1D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:128
std::string convertTitleToID(std::string title) const
Create an ID string from a title string.
list i
Definition: ana.py:128
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)
static std::string toString(const AIDA::IProfile2D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:147
ID class for Histogram and Ntuples.
Definition: GaudiHistoID.h:44
bool numeric() const
Is this ID numeric.
Definition: GaudiHistoID.h:64
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:2599
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
KeyedObjectManager< map > Map
Forward declaration of specialized std::map-like object manager.
std::string toString(const AIDA::IHistogram1D *histo) const
make the string representation according to the default format
void initGaudiHistosConstructor()
Constructor initialisation and job options.