HistogramSvc.cpp
Go to the documentation of this file.
1 #ifdef __ICC
2 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
3 // TODO: To be removed, since it comes from ROOT TMathBase.h
4 #pragma warning(disable:2259)
5 #endif
6 #ifdef WIN32
7 // Disable warning
8 // warning C4996: 'sprintf': This function or variable may be unsafe.
9 // coming from TString.h
10 #pragma warning(disable:4996)
11 #endif
12 // ============================================================================
13 // Include files
14 // ============================================================================
15 // STD&STL
16 // ============================================================================
17 #include <cstdlib>
18 #include <stdexcept>
19 #include <sstream>
20 // ============================================================================
21 // GaudiKernel
22 // ============================================================================
23 #include "GaudiKernel/Property.h"
25 #include "GaudiKernel/DataObject.h"
28 // ============================================================================
29 // Local
30 // ============================================================================
31 #include "HistogramSvc.h"
32 // ============================================================================
33 // Instantiation of a factory class used by clients
35 // ============================================================================
36 using namespace AIDA;
37 // ============================================================================
38 namespace
39 {
40  // ==========================================================================
41  inline std::string histoAddr
42  ( const std::string& name)
43  {
44  if ( 0 == name.find ( "/stat/" ) ){ return std::string( name , 6 ) ; }
45  return name ;
46  }
47  // ==========================================================================
48  inline std::string histoAddr
49  ( const DataObject* obj ,
50  const std::string& rel )
51  {
52  if ( !obj ) { return rel ; }
53  IRegistry* reg = obj->registry() ;
54  if ( !reg ) { return rel ; }
55  const std::string& name = reg->identifier() ;
56  //
57  if ( rel .empty() ) { return histoAddr ( name ) ; }
58  if ( '/' == name[name.size()-1] ||
59  '/' == rel[0] ) { return histoAddr ( name + rel ) ; }
60  return histoAddr ( name + "/" + rel ) ;
61  }
62  // ==========================================================================
63 }
64 //------------------------------------------------------------------------------
65 StatusCode HistogramSvc::registerObject(CSTR full, IBaseHistogram* obj) {
67  return registerObject(split.first, split.second, obj);
68 }
69 //------------------------------------------------------------------------------
71 (DataObject* pPar,CSTR obj,IBaseHistogram* hObj) {
72  // Set the histogram id
73  if (obj[0] == SEPARATOR) {
74  // hObj->setTitle(obj.substr(1) + "|" + hObj->title());
75  if (!hObj->annotation().addItem("id", obj.substr(1)))
76  hObj->annotation().setValue("id", obj.substr(1));
77  }
78  else {
79  // hObj->setTitle(obj + "|" + hObj->title());
80  if (!hObj->annotation().addItem("id", obj))
81  hObj->annotation().setValue("id", obj);
82  }
83  // Register the histogram in the histogram data store
84  return DataSvc::registerObject(pPar,obj,__cast(hObj));
85 }
86 
87 // Helper for 2D projections
88 AIDA::IHistogram2D*
89 HistogramSvc::i_project(CSTR nameAndTitle,const IHistogram3D& h, CSTR dir) {
90  TH3D *h3d = Gaudi::getRepresentation<IHistogram3D,TH3D>(h);
91  if ( h3d ) {
92  TH2D *h2d = dynamic_cast<TH2D*>(h3d->Project3D(dir.c_str()));
93  if ( h2d ) {
95  if ( r.second && registerObject(nameAndTitle,r.second).isSuccess() ) {
96  return r.second;
97  }
98  }
99  }
100  return nullptr;
101 }
102 
103 //------------------------------------------------------------------------------
104 // ASCII output
105 //------------------------------------------------------------------------------
106 std::ostream& HistogramSvc::print(IBaseHistogram* h, std::ostream& s) const {
107  Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
108  if (b) return b->print(s);
109  error() << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
110  << endmsg;
111  return s;
112 }
113 //------------------------------------------------------------------------------
114 std::ostream& HistogramSvc::write(IBaseHistogram* h, std::ostream& s) const {
115  Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
116  if (b) return b->write(s);
117  error() << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
118  << endmsg;
119  return s;
120 }
121 //------------------------------------------------------------------------------
122 int HistogramSvc::write(IBaseHistogram* h, const char* file_name) const {
123  Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
124  if (b) return b->write(file_name);
125  error() << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
126  << endmsg;
127  return 0;
128 }
129 //------------------------------------------------------------------------------
131  std::string tmp = full;
132  if (tmp[0] != SEPARATOR) {
133  tmp.insert(tmp.begin(), SEPARATOR);
134  tmp.insert(tmp.begin(), m_rootName.begin(), m_rootName.end());
135  }
136  // Remove trailing "/" from newPath if it exists
137  if (tmp.rfind(SEPARATOR) == tmp.length()-1) {
138  tmp.erase(tmp.rfind(SEPARATOR),1);
139  }
140  int sep = tmp.rfind(SEPARATOR);
141  return { tmp.substr(0,sep), tmp.substr(sep) };
142 }
143 //------------------------------------------------------------------------------
145  std::string tmpPath = newPath;
146  if (tmpPath[0] != SEPARATOR) {
147  tmpPath.insert(tmpPath.begin(), SEPARATOR);
148  tmpPath.insert(tmpPath.begin(), m_rootName.begin(), m_rootName.end());
149  }
150  // Remove trailing "/" from newPath if it exists
151  if (tmpPath.rfind(SEPARATOR) == tmpPath.length()-1) {
152  tmpPath.erase(tmpPath.rfind(SEPARATOR),1);
153  }
154  DataObject* pObject = nullptr;
155  StatusCode sc = DataSvc::findObject(tmpPath, pObject);
156  if(sc.isSuccess()) {
157  return pObject;
158  }
159  int sep = tmpPath.rfind(SEPARATOR);
160  std::string rest(tmpPath, sep+1, tmpPath.length()-sep);
161  std::string subPath(tmpPath, 0, sep);
162  if(0 != sep) {
163  createPath(subPath);
164  }
165  else {
166  error() << "Unable to create the histogram path" << endmsg;
167  return nullptr;
168  }
169  pObject = createDirectory(subPath, rest);
170  return pObject;
171 }
172 //------------------------------------------------------------------------------
174  std::unique_ptr<DataObject> directory{ new DataObject() };
175  if (directory) {
176  DataObject* pnode;
177  StatusCode status = DataSvc::retrieveObject(parentDir, pnode);
178  if(status.isSuccess()) {
179  status = DataSvc::registerObject(pnode, subDir, directory.get());
180  if (!status.isSuccess()) {
181  error() << "Unable to create the histogram directory: "
182  << parentDir << "/" << subDir << endmsg;
183  return nullptr;
184  }
185  }
186  else {
187  error() << "Unable to create the histogram directory: "
188  << parentDir << "/" << subDir << endmsg;
189  return nullptr;
190  }
191  }
192  return directory.release();
193 }
194 //------------------------------------------------------------------------------
196  setDataLoader( nullptr ).ignore();
197  clearStore().ignore();
198 }
199 //------------------------------------------------------------------------------
201  using Parser = Gaudi::Utils::AttribStringParser;
202  DataObject* pO = nullptr;
203  StatusCode status = this->findObject(m_rootName, pO);
204  if (status.isSuccess()) {
205  std::string::size_type loc = ident.find(" ");
206  std::string filename, auth, svc = "", typ = "";
207  std::string logname = ident.substr(0, loc);
208  for (auto attrib: Parser(ident.substr(loc+1))) {
209  switch(::toupper(attrib.tag[0])) {
210  case 'F': // FILE='<file name>'
211  case 'D': // DATAFILE='<file name>'
212  filename = std::move(attrib.value);
213  break;
214  case 'T': // TYP='<HBOOK,ROOT,OBJY,...>'
215  typ = std::move(attrib.value);
216  break;
217  default:
218  break;
219  }
220  }
221  if (typ.length() > 0) {
222  // Now add the registry entry to the store
223  std::string entryname = m_rootName;
224  entryname += '/';
225  entryname += logname;
226  GenericAddress* pA = nullptr;
227  switch(::toupper(typ[0])) {
228  case 'H':
229  pA=new GenericAddress(HBOOK_StorageType,CLID_StatisticsFile,
230  filename,entryname,0,'O');
231  break;
232  case 'R':
233  pA=new GenericAddress(ROOT_StorageType,CLID_StatisticsFile,
234  filename,entryname,0,'O');
235  break;
236  }
237  if (pA) {
238  status = registerAddress(pO, logname, pA);
239  if (status.isSuccess()) {
240  info() << "Added stream file:" << filename
241  << " as " << logname << endmsg;
242  return status;
243  }
244  pA->release();
245  }
246  }
247  }
248  error() << "Cannot add " << ident << " invalid filename!" << endmsg;
249  return StatusCode::FAILURE;
250 }
251 //------------------------------------------------------------------------------
253  StatusCode status = DataSvc::initialize();
254  // Set root object
255  if (status.isSuccess()) {
256  std::unique_ptr<DataObject> rootObj{ new DataObject() };
257  status = setRoot("/stat", rootObj.get());
258  if (status.isSuccess()) {
259  rootObj.release();
260  } else {
261  error() << "Unable to set hstogram data store root." << endmsg;
262  return status;
263  }
264  auto svc = service<IConversionSvc>("HistogramPersistencySvc",true);
265  if ( svc ) {
266  setDataLoader( svc.get() ).ignore();
267  } else {
268  error() << "Could not find HistogramPersistencySvc." << endmsg;
269  return StatusCode::FAILURE;
270  }
271  // Connect all input streams (if any)
272  for (auto & j : m_input) {
273  status = connectInput(j);
274  if (!status.isSuccess()) return status;
275  }
276  }
277  if ( !m_defs1D.empty() )
278  {
279  info() << " Predefined 1D-Histograms: " << endmsg ;
280  for ( const auto& ih : m_defs1D )
281  {
282  info()
283  << " Path='" << ih.first << "'"
284  << " Description " << ih.second << endmsg ;
285  }
286  }
287  return status;
288 }
289 //------------------------------------------------------------------------------
291  return StatusCode::SUCCESS;
292 }
293 //------------------------------------------------------------------------------
294 IHistogram1D* HistogramSvc::sliceX
295 (CSTR name,const IHistogram2D& h,int idxY1,int idxY2) {
296  std::pair<DataObject*,IHistogram1D*> o(nullptr,nullptr);
297  try {
298  int firstbin = Gaudi::Axis::toRootIndex(idxY1,h.yAxis().bins());
299  int lastbin = Gaudi::Axis::toRootIndex(idxY2,h.yAxis().bins());
300  o = Gaudi::slice1DX(name, h, firstbin, lastbin);
301  }
302  catch ( ... ) {
303  throw GaudiException("Cannot cast 2D histogram to H2D to create sliceX `"
304  + name + "'!", "HistogramSvc", StatusCode::FAILURE);
305  }
306  if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() ) {
307  return o.second;
308  }
309  delete o.first;
310  throw GaudiException("Cannot create sliceX `" + name + "' of 2D histogram!",
311  "HistogramSvc", StatusCode::FAILURE);
312 }
313 //------------------------------------------------------------------------------
314 IHistogram1D*
315 HistogramSvc::sliceY(CSTR name,const IHistogram2D& h,int indexX1,int indexX2) {
316  std::pair<DataObject*,IHistogram1D*> o(nullptr,nullptr);
317  try {
318  int firstbin = Gaudi::Axis::toRootIndex( indexX1, h.xAxis().bins() );
319  int lastbin = Gaudi::Axis::toRootIndex( indexX2, h.xAxis().bins() );
320  o = Gaudi::slice1DY(name, h, firstbin, lastbin);
321  }
322  catch ( ... ) {
323  throw GaudiException("Cannot create sliceY `"+name+"'!",
324  "HistogramSvc",StatusCode::FAILURE);
325  }
326  // name stands here for the fullPath of the histogram
327  if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() ) {
328  return o.second;
329  }
330  delete o.first;
331  throw GaudiException("Cannot create sliceY `"+name+"' of 2D histogram!",
332  "HistogramSvc", StatusCode::FAILURE);
333 }
334 //------------------------------------------------------------------------------
335 bool HistogramSvc::destroy( IBaseHistogram* hist ) {
336  StatusCode sc = unregisterObject( dynamic_cast<IHistogram*>(hist) );
337  if ( !sc.isSuccess() ) return false;
338  delete hist;
339  return true;
340 }
341 // ============================================================================
342 AIDA::IHistogram1D* HistogramSvc::book
343 (DataObject* pPar, CSTR rel, CSTR title, DBINS(x))
344 {
345  if ( m_defs1D.empty () )
346  { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
347  std::string hn = histoAddr ( pPar , rel ) ;
348  auto ifound = m_defs1D.find( hn ) ;
349  if ( m_defs1D.end() == ifound )
350  { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
351  if (msgLevel(MSG::DEBUG)) {
352  debug()
353  << " Redefine the parameters for the histogram '" + hn + "' to be "
354  << ifound->second
355  << endmsg;
356  }
357  m_mods1D.insert ( hn ) ;
358  return i_book ( pPar , rel , ifound -> second.title () ,
360  ( ifound -> second.title () ,
361  ifound -> second.bins () ,
362  ifound -> second.lowEdge () ,
363  ifound -> second.lowEdge () ) ) ;
364 }
365 // ============================================================================
366 // constructor
367 // ============================================================================
369  : base_class(nam, svc)
370 {
371  // Properties can be declared here
372  m_rootName = "/stat";
373  m_rootCLID = CLID_DataObject;
374  declareProperty ( "Input", m_input);
375  declareProperty ( "Predefined1DHistos" , m_defs1D ,
376  "Histograms with predefined parameters" ) ;
377  // update handler
378  Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
380 
381 }
382 // ============================================================================
383 // handler to be invoked for updating property m_defs1D
384 // ============================================================================
385 namespace
386 {
387  inline size_t removeLeading
388  ( HistogramSvc::Histo1DMap& m , const std::string& lead = "/stat/")
389  {
390  for ( auto it = m.begin() ; m.end() != it ; ++it )
391  {
392  if ( 0 == it->first.find ( lead ) )
393  {
394  std::string addr = std::string( it->first , lead.size() ) ;
395  Gaudi::Histo1DDef hdef = it->second ;
396  m.erase ( it ) ; // remove
397  m[addr] = hdef ; // insert
398  return 1 + removeLeading ( m , lead ) ; // return
399  }
400  }
401  return 0 ;
402  }
403 }
404 // ============================================================================
406 {
407  // check and remove the leading '/stat/'
408  removeLeading ( m_defs1D , "/stat/" ) ;
409 }
410 // ============================================================================
411 // finalize the service
413 {
414  if ( !m_mods1D.empty() )
415  {
416  if (msgLevel(MSG::DEBUG))
417  debug()
418  << " Substituted histograms #" << m_mods1D.size() << " : " << endmsg;
419  for ( const auto& ih : m_mods1D )
420  {
421  if (msgLevel(MSG::DEBUG))
422  debug() << " Path='" << ih << "'" ;
423  auto im = m_defs1D.find( ih ) ;
424  if ( m_defs1D.end() != im ) { debug() << " " << im->second ; }
425  }
426  m_mods1D.clear() ;
427  }
428  return DataSvc::finalize () ;
429 }
430 // ============================================================================
431 // The END
432 // ============================================================================
Parse attribute strings allowing iteration over the various attributes.
std::pair< DataObject *, AIDA::IHistogram1D * > slice1DY(const std::string &name, const AIDA::IHistogram2D &h, int firstbin, int lastbin)
Create 1D slice from 2D histogram.
T empty(T...args)
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
const long HBOOK_StorageType
Definition: ClassID.h:56
std::set< std::string > m_mods1D
Definition: HistogramSvc.h:969
std::ostream & write(Base *h, std::ostream &s=std::cout) const override
Write (ASCII) the 1D histogram table into the output stream.
H1D * book(CSTR par, CSTR rel, CSTR title, DBINS(x)) override
Book histogram and register it with the histogram data store.
Definition: HistogramSvc.h:211
constexpr char SEPARATOR
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
virtual Property & declareUpdateHandler(std::function< void(Property &)> fun)
set new callback for update
Definition: Property.cpp:72
std::pair< DataObject *, AIDA::IHistogram1D * > createH1D(const AIDA::IHistogram1D &hist)
Copy constructor.
bool isSuccess() const
Test for a status code of SUCCESS.
Definition: StatusCode.h:76
unsigned long release() override
release reference to object
StatusCode setRoot(std::string root_name, DataObject *pRootObj) override
Initialize data store for new event by giving new event path and root object.
Definition: DataSvc.cpp:153
StatusCode findObject(IRegistry *pReg, CSTR path, P1D *&obj) override
Definition: HistogramSvc.h:676
StatusCode setDataLoader(IConversionSvc *svc, IDataProviderSvc *dpsvc=nullptr) override
IDataManagerSvc: IDataManagerSvc: Pass a default data loader to the service and optionally a data pro...
Definition: DataSvc.cpp:202
std::string m_rootName
Name of root event.
Definition: DataSvc.h:55
T rfind(T...args)
virtual std::ostream & print(std::ostream &s) const =0
Print histogram to output stream.
virtual std::ostream & write(std::ostream &s) const =0
Write (binary) histogram to output stream.
~HistogramSvc() override
Destructor.
StatusCode unregisterObject(Base *obj) override
Definition: HistogramSvc.h:572
T end(T...args)
Generic Transient Address.
StatusCode registerObject(const std::string &fullPath, DataObject *pObject) override
Register object with the data store.
Definition: DataSvc.cpp:356
GAUDI_API Property * getProperty(const IProperty *p, const std::string &name)
simple function which gets the property with given name from the component
Definition: Property.cpp:278
H2D * i_project(CSTR nameAndTitle, const H3D &h, CSTR dir)
Helper for 2D projections.
StatusCode registerAddress(const std::string &fullPath, IOpaqueAddress *pAddress) override
IDataManagerSvc: Register object address with the data store.
Definition: DataSvc.cpp:244
DBaseEntries m_input
Input streams.
Definition: HistogramSvc.h:138
StatusCode initialize() override
Initialise the service.
StatusCode connectInput(CSTR ident)
Connect input histogram file to the service.
GaudiKernel.
Definition: Fill.h:8
Histo1DMap m_defs1D
Definition: HistogramSvc.h:966
IRegistry * registry() const
Get pointer to Registry.
Definition: DataObject.h:74
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
StatusCode finalize() override
finalize the service
constexpr double second
STL class.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
std::pair< std::string, std::string > i_splitPath(CSTR full)
Split full path into its components.
#define BINS(x)
Definition: HistogramSvc.h:39
DataObject * createPath(CSTR newPath) override
Create all directories in a given full path.
bool destroy(IBaseHistogram *hist) override
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
constexpr double m
Definition: SystemOfUnits.h:93
void clear(STATE_TYPE _i=std::ios_base::failbit)
Definition: MsgStream.h:222
H1D * sliceY(CSTR name, const H2D &h, int indexX) override
Definition: HistogramSvc.h:773
Simple helper class for description of 1D-histogram The class is targeted to act as the primary "hist...
Definition: HistoDef.h:30
StatusCode findObject(const std::string &fullPath, DataObject *&pObject) override
Find object identified by its full path in the data store.
Definition: DataSvc.cpp:828
T erase(T...args)
std::pair< DataObject *, AIDA::IHistogram2D * > createH2D(const AIDA::IHistogram2D &hist)
Copy constructor.
void update1Ddefs(Property &)
handler to be invoked for updating property m_defs1D
std::pair< DataObject *, AIDA::IHistogram1D * > slice1DX(const std::string &name, const AIDA::IHistogram2D &h, int firstbin, int lastbin)
Create 1D slice from 2D histogram.
static DataObject * __cast(T *p)
Definition: HistogramSvc.h:170
The IRegistry represents the entry door to the environment any data object residing in a transient da...
Definition: IRegistry.h:22
const long ROOT_StorageType
Definition: ClassID.h:52
std::ostream & print(Base *h, std::ostream &s=std::cout) const override
Print (ASCII) the 1D histogram into the output stream.
StatusCode finalize() override
Service initialization.
Definition: DataSvc.cpp:1188
StatusCode registerObject(CSTR parent, CSTR rel, Base *obj) override
Definition: HistogramSvc.h:557
StatusCode retrieveObject(IRegistry *pDirectory, const std::string &path, DataObject *&pObject) override
Retrieve object from data store.
Definition: DataSvc.cpp:763
T move(T...args)
T insert(T...args)
T find(T...args)
T size(T...args)
Property base class allowing Property* collections to be "homogeneous".
Definition: Property.h:38
#define DBINS(x)
Definition: HistogramSvc.h:38
Common base class for all histograms Use is solely functional to minimize dynamic_casts inside Histog...
Definition: HistogramBase.h:22
STL class.
HistogramSvc(const std::string &name, ISvcLocator *svc)
Statndard Constructor.
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
StatusCode initialize() override
Service initialization.
Definition: DataSvc.cpp:1153
T begin(T...args)
T c_str(T...args)
H1D * sliceX(CSTR name, const H2D &h, int indexY) override
Definition: HistogramSvc.h:771
string s
Definition: gaudirun.py:245
T substr(T...args)
CLID m_rootCLID
Integer Property corresponding to CLID of root entry.
Definition: DataSvc.h:53
static int toRootIndex(int index, int nbins)
Definition: Axis.h:37
virtual const id_type & identifier() const =0
Full identifier (or key)
DataObject * createDirectory(CSTR parentDir, CSTR subDir) override
Create a sub-directory in a directory.
void ignore() const
Definition: StatusCode.h:108
Property * declareProperty(const std::string &name, T &property, const std::string &doc="none") const
Declare the named property.
Definition: Service.h:215
StatusCode reinitialize() override
Initialise the service.
MSG::Level msgLevel() const
get the output level from the embedded MsgStream
A DataObject is the base class of any identifiable object on any data store.
Definition: DataObject.h:30
STL class.
void toupper(std::string &s)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
StatusCode clearStore() override
IDataManagerSvc: Remove all data objects in the data store.
Definition: DataSvc.cpp:114
HistogramSvc class definition.
Definition: HistogramSvc.h:47