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"
26 #include "GaudiKernel/IHistogramSvc.h"
27 // ============================================================================
28 // GaudiUtils
29 // ============================================================================
30 #include "GaudiUtils/HistoTableFormat.h"
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>
58  std::map<typename C::key_type, typename C::mapped_type> operator()(const C& c) const {
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  {
285  msg << std::endl << Gaudi::Utils::Histos::format
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>
366 bool GaudiHistos<PBASE>::noHistos() const
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>
444 unsigned int GaudiHistos<PBASE>::totalNumberOfHistos() const
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>
485 std::string GaudiHistos<PBASE>::convertTitleToID( std::string title ) const
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 >
508 std::string GaudiHistos<PBASE>::histoPath () const
509 {
510  std::string path = histoTopDir() + histoDir();
511  return splitHistoDir() ? dirHbookName(path) : path;
512 }
513 // ============================================================================
514 // 1D
515 #include "GaudiAlg/GaudiHistos_1DFixedBinning.icpp"
516 #include "GaudiAlg/GaudiHistos_1DVariableBinning.icpp"
517 // 2D
518 #include "GaudiAlg/GaudiHistos_2DFixedBinning.icpp"
519 #include "GaudiAlg/GaudiHistos_2DVariableBinning.icpp"
520 // 3D
521 #include "GaudiAlg/GaudiHistos_3DFixedBinning.icpp"
522 #include "GaudiAlg/GaudiHistos_3DVariableBinning.icpp"
523 // 1D Profile
524 #include "GaudiAlg/GaudiHistos_1DProfFixedBinning.icpp"
525 #include "GaudiAlg/GaudiHistos_1DProfVariableBinning.icpp"
526 // 2D Profile
527 #include "GaudiAlg/GaudiHistos_2DProfFixedBinning.icpp"
528 #include "GaudiAlg/GaudiHistos_2DProfVariableBinning.icpp"
529 // ============================================================================
530 // The END
531 // ============================================================================
532 #endif // GAUDIALG_GAUDIHISTOS_ICPP
533 // ============================================================================
tuple c
Definition: gaudirun.py:392
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
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
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
bool noHistos() const
Check if all histogram maps are empty.
GaudiAlg::ID HistoID
The actual type for histogram identifier.
Definition: HistoID.h:23
auto begin(reverse_wrapper< T > &w)
Definition: reverse.h:45
void newHistoID(const std::string &title, HistoID &ID) const
Create a new histogram ID using the given title.
list path
Definition: __init__.py:15
Collection of useful utilities for manipulations with AIDA hisgograms.
Definition: Fill.h:27
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
GaudiKernel.
Definition: Fill.h:8
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.
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.
auto end(reverse_wrapper< T > &w)
Definition: reverse.h:47
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
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.
static std::string toString(const AIDA::IHistogram3D *aida, const GaudiAlg::HistoID &ID)
Definition: Print.cpp:107
GAUDI_API std::string format(const int ID=Default)
get the format by enum
std::string histoPath() const
get the constructed histogram path
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
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
GAUDI_API std::string header(const int ID=Default)
get the recommended header by enum
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
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
GAUDI_API std::string htitle(const AIDA::IBaseHistogram *histo, const std::string &title="")
get the title
Definition: Fill.cpp:138
KeyedObjectManager< map > Map
Forward declaration of specialized std::map-like object manager.
void initGaudiHistosConstructor()
Constructor initialisation and job options.