All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
HistogramSvc.cpp
Go to the documentation of this file.
1 // $Id: HistogramSvc.cpp,v 1.28 2007/09/26 16:14:47 marcocle Exp $
2 #ifdef __ICC
3 // disable icc remark #2259: non-pointer conversion from "X" to "Y" may lose significant bits
4 // TODO: To be removed, since it comes from ROOT TMathBase.h
5 #pragma warning(disable:2259)
6 #endif
7 #ifdef WIN32
8 // Disable warning
9 // warning C4996: 'sprintf': This function or variable may be unsafe.
10 // coming from TString.h
11 #pragma warning(disable:4996)
12 #endif
13 // ============================================================================
14 // Include files
15 // ============================================================================
16 // STD&STL
17 // ============================================================================
18 #include <cstdlib>
19 #include <stdexcept>
20 #include <sstream>
21 // ============================================================================
22 // GaudiKernel
23 // ============================================================================
24 #include "GaudiKernel/xtoa.h"
25 #include "GaudiKernel/Property.h"
26 #include "GaudiKernel/Tokenizer.h"
27 #include "GaudiKernel/MsgStream.h"
28 #include "GaudiKernel/DataObject.h"
29 #include "GaudiKernel/IConversionSvc.h"
30 #include "GaudiKernel/GenericAddress.h"
31 // ============================================================================
32 // Local
33 // ============================================================================
34 #include "HistogramSvc.h"
35 // ============================================================================
36 // Instantiation of a factory class used by clients
38 // ============================================================================
39 using namespace AIDA;
40 // ============================================================================
41 namespace
42 {
43  // ==========================================================================
44  inline std::string histoAddr
45  ( const std::string& name)
46  {
47  if ( 0 == name.find ( "/stat/" ) ){ return std::string( name , 6 ) ; }
48  return name ;
49  }
50  // ==========================================================================
51  inline std::string histoAddr
52  ( const DataObject* obj ,
53  const std::string& rel )
54  {
55  if ( 0 == obj ) { return rel ; }
56  IRegistry* reg = obj->registry() ;
57  if ( 0 == reg ) { return rel ; }
58  const std::string& name = reg->identifier() ;
59  //
60  if ( rel .empty() ) { return histoAddr ( name ) ; }
61  if ( '/' == name[name.size()-1] ||
62  '/' == rel[0] ) { return histoAddr ( name + rel ) ; }
63  return histoAddr ( name + "/" + rel ) ;
64  }
65  // ==========================================================================
66 }
67 //------------------------------------------------------------------------------
68 std::string HistogramSvc::_STR(int i) {
69  std::ostringstream txt; txt << i;
70  return txt.str();
71 }
72 //------------------------------------------------------------------------------
73 StatusCode HistogramSvc::registerObject(CSTR full, IBaseHistogram* obj) {
74  std::pair<std::string,std::string> split=i_splitPath(full);
75  return registerObject(split.first, split.second, obj);
76 }
77 //------------------------------------------------------------------------------
79 (DataObject* pPar,CSTR obj,IBaseHistogram* hObj) {
80  // Set the histogram id
81  if (obj[0] == SEPARATOR) {
82  // hObj->setTitle(obj.substr(1) + "|" + hObj->title());
83  if (!hObj->annotation().addItem("id", obj.substr(1)))
84  hObj->annotation().setValue("id", obj.substr(1));
85  }
86  else {
87  // hObj->setTitle(obj + "|" + hObj->title());
88  if (!hObj->annotation().addItem("id", obj))
89  hObj->annotation().setValue("id", obj);
90  }
91  // Register the histogram in the histogram data store
92  return DataSvc::registerObject(pPar,obj,__cast(hObj));
93 }
94 
95 // Helper for 2D projections
96 AIDA::IHistogram2D*
97 HistogramSvc::i_project(CSTR nameAndTitle,const IHistogram3D& h, CSTR dir) {
98  TH3D *h3d = Gaudi::getRepresentation<IHistogram3D,TH3D>(h);
99  if ( h3d ) {
100  TH2D *h2d = dynamic_cast<TH2D*>(h3d->Project3D(dir.c_str()));
101  if ( h2d ) {
102  std::pair<DataObject*,H2D*> r=Gaudi::createH2D(h2d);
103  if ( r.second && registerObject(nameAndTitle,r.second).isSuccess() ) {
104  return r.second;
105  }
106  }
107  }
108  return 0;
109 }
110 
111 //------------------------------------------------------------------------------
112 // ASCII output
113 //------------------------------------------------------------------------------
114 std::ostream& HistogramSvc::print(IBaseHistogram* h, std::ostream& s) const {
115  Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
116  if(0 != b) return b->print(s);
117  MsgStream log(msgSvc(), name());
118  log << MSG::ERROR << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
119  << endmsg;
120  return s;
121 }
122 //------------------------------------------------------------------------------
123 std::ostream& HistogramSvc::write(IBaseHistogram* h, std::ostream& s) const {
124  Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
125  if(0 != b) return b->write(s);
126  MsgStream log(msgSvc(), name());
127  log << MSG::ERROR << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
128  << endmsg;
129  return s;
130 }
131 //------------------------------------------------------------------------------
132 int HistogramSvc::write(IBaseHistogram* h, const char* file_name) const {
133  Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
134  if(0 != b) return b->write(file_name);
135  MsgStream log(msgSvc(), name());
136  log << MSG::ERROR << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
137  << endmsg;
138  return 0;
139 }
140 //------------------------------------------------------------------------------
141 std::pair<std::string,std::string> HistogramSvc::i_splitPath(CSTR full) {
142  std::string tmp = full;
143  if (tmp[0] != SEPARATOR) {
144  tmp.insert(tmp.begin(), SEPARATOR);
145  tmp.insert(tmp.begin(), m_rootName.begin(), m_rootName.end());
146  }
147  // Remove trailing "/" from newPath if it exists
148  if (tmp.rfind(SEPARATOR) == tmp.length()-1) {
149  tmp.erase(tmp.rfind(SEPARATOR),1);
150  }
151  int sep = tmp.rfind(SEPARATOR);
152  return std::pair<std::string,std::string>
153  (tmp.substr(0,sep),tmp.substr(sep,tmp.length()-sep));
154 }
155 //------------------------------------------------------------------------------
157  std::string tmpPath = newPath;
158  if (tmpPath[0] != SEPARATOR) {
159  tmpPath.insert(tmpPath.begin(), SEPARATOR);
160  tmpPath.insert(tmpPath.begin(), m_rootName.begin(), m_rootName.end());
161  }
162  // Remove trailing "/" from newPath if it exists
163  if (tmpPath.rfind(SEPARATOR) == tmpPath.length()-1) {
164  tmpPath.erase(tmpPath.rfind(SEPARATOR),1);
165  }
166  DataObject* pObject = 0;
167  StatusCode sc = DataSvc::findObject(tmpPath, pObject);
168  if(sc.isSuccess()) {
169  return pObject;
170  }
171  int sep = tmpPath.rfind(SEPARATOR);
172  std::string rest(tmpPath, sep+1, tmpPath.length()-sep);
173  std::string subPath(tmpPath, 0, sep);
174  if(0 != sep) {
175  createPath(subPath);
176  }
177  else {
178  MsgStream log(msgSvc(), name());
179  log << MSG::ERROR << "Unable to create the histogram path" << endmsg;
180  return 0;
181  }
182  pObject = createDirectory(subPath, rest);
183  return pObject;
184 }
185 //------------------------------------------------------------------------------
187  DataObject* directory = new DataObject();
188  if (0 != directory) {
189  DataObject* pnode;
190  StatusCode status = DataSvc::retrieveObject(parentDir, pnode);
191  if(status.isSuccess()) {
192  status = DataSvc::registerObject(pnode, subDir, directory);
193  if (!status.isSuccess()) {
194  MsgStream log(msgSvc(), name());
195  log << MSG::ERROR << "Unable to create the histogram directory: "
196  << parentDir << "/" << subDir << endmsg;
197  delete directory;
198  return 0;
199  }
200  }
201  else {
202  MsgStream log(msgSvc(), name());
203  log << MSG::ERROR << "Unable to create the histogram directory: "
204  << parentDir << "/" << subDir << endmsg;
205  delete directory;
206  return 0;
207  }
208  }
209  return directory;
210 }
211 //------------------------------------------------------------------------------
213  setDataLoader( 0 ).ignore();
214  clearStore().ignore();
215 }
216 //------------------------------------------------------------------------------
218  MsgStream log (msgSvc(), name());
219  DataObject* pO = 0;
220  StatusCode status = this->findObject(m_rootName, pO);
221  if (status.isSuccess()) {
222  Tokenizer tok(true);
223  std::string::size_type loc = ident.find(" ");
224  std::string filename, auth, svc = "", typ = "";
225  std::string logname = ident.substr(0,loc);
226  tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
227  for (Tokenizer::Items::iterator i = tok.items().begin();
228  i != tok.items().end(); i++) {
229  CSTR tag = (*i).tag();
230  switch(::toupper(tag[0])) {
231  case 'F': // FILE='<file name>'
232  case 'D': // DATAFILE='<file name>'
233  filename = (*i).value();
234  break;
235  case 'T': // TYP='<HBOOK,ROOT,OBJY,...>'
236  typ = (*i).value();
237  break;
238  default:
239  break;
240  }
241  }
242  if (typ.length() > 0) {
243  // Now add the registry entry to the store
244  std::string entryname = m_rootName;
245  entryname += '/';
246  entryname += logname;
247  GenericAddress* pA = 0;
248  switch(::toupper(typ[0])) {
249  case 'H':
250  pA=new GenericAddress(HBOOK_StorageType,CLID_StatisticsFile,
251  filename,entryname,0,'O');
252  break;
253  case 'R':
254  pA=new GenericAddress(ROOT_StorageType,CLID_StatisticsFile,
255  filename,entryname,0,'O');
256  break;
257  }
258  if (0 != pA) {
259  status = registerAddress(pO, logname, pA);
260  if (status.isSuccess()) {
261  log << MSG::INFO << "Added stream file:" << filename
262  << " as " << logname << endmsg;
263  return status;
264  }
265  pA->release();
266  }
267  }
268  }
269  log << MSG::ERROR << "Cannot add " << ident << " invalid filename!" << endmsg;
270  return StatusCode::FAILURE;
271 }
272 //------------------------------------------------------------------------------
274  MsgStream log(msgSvc(), name());
275  StatusCode status = DataSvc::initialize();
276  // Set root object
277  if (status.isSuccess()) {
278  DataObject* rootObj = new DataObject();
279  status = setRoot("/stat", rootObj);
280  if (!status.isSuccess()) {
281  log << MSG::ERROR << "Unable to set hstogram data store root." << endmsg;
282  delete rootObj;
283  return status;
284  }
285  IConversionSvc* svc = 0;
286  status = service("HistogramPersistencySvc",svc,true);
287  if ( status.isSuccess() ) {
288  setDataLoader( svc ).ignore();
289  svc->release();
290  }
291  else {
292  log << MSG::ERROR << "Could not find HistogramPersistencySvc." << endmsg;
293  return status;
294  }
295  // Connect all input streams (if any)
296  for (DBaseEntries::iterator j = m_input.begin(); j != m_input.end(); j++) {
297  status = connectInput(*j);
298  if (!status.isSuccess()) {
299  return status;
300  }
301  }
302  }
303  if ( !m_defs1D.empty() )
304  {
305  log << MSG::INFO << " Predefined 1D-Histograms: " << endmsg ;
306  for ( Histo1DMap::const_iterator ih = m_defs1D.begin() ;
307  m_defs1D.end() != ih ; ++ih )
308  {
309  log << MSG::INFO
310  << " Path='" << ih->first << "'"
311  << " Description " << ih->second << endmsg ;
312  }
313  }
314  return status;
315 }
316 //------------------------------------------------------------------------------
318  return StatusCode::SUCCESS;
319 }
320 //------------------------------------------------------------------------------
322 (CSTR name,const IHistogram2D& h,int idxY1,int idxY2) {
323  std::pair<DataObject*,IHistogram1D*> o(0,0);
324  try {
325  int firstbin = Gaudi::Axis::toRootIndex(idxY1,h.yAxis().bins());
326  int lastbin = Gaudi::Axis::toRootIndex(idxY2,h.yAxis().bins());
327  o = Gaudi::slice1DX(name, h, firstbin, lastbin);
328  }
329  catch ( ... ) {
330  throw GaudiException("Cannot cast 2D histogram to H2D to create sliceX `"
331  + name + "'!", "HistogramSvc", StatusCode::FAILURE);
332  }
333  if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() ) {
334  return o.second;
335  }
336  delete o.first;
337  throw GaudiException("Cannot create sliceX `" + name + "' of 2D histogram!",
338  "HistogramSvc", StatusCode::FAILURE);
339 }
340 //------------------------------------------------------------------------------
342 HistogramSvc::sliceY(CSTR name,const IHistogram2D& h,int indexX1,int indexX2) {
343  std::pair<DataObject*,IHistogram1D*> o(0,0);
344  try {
345  int firstbin = Gaudi::Axis::toRootIndex( indexX1, h.xAxis().bins() );
346  int lastbin = Gaudi::Axis::toRootIndex( indexX2, h.xAxis().bins() );
347  o = Gaudi::slice1DY(name, h, firstbin, lastbin);
348  }
349  catch ( ... ) {
350  throw GaudiException("Cannot create sliceY `"+name+"'!",
351  "HistogramSvc",StatusCode::FAILURE);
352  }
353  // name stands here for the fullPath of the histogram
354  if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() ) {
355  return o.second;
356  }
357  delete o.first;
358  throw GaudiException("Cannot create sliceY `"+name+"' of 2D histogram!",
359  "HistogramSvc", StatusCode::FAILURE);
360 }
361 //------------------------------------------------------------------------------
362 bool HistogramSvc::destroy( IBaseHistogram* hist ) {
363  StatusCode sc = unregisterObject( dynamic_cast<IHistogram*>(hist) );
364  if ( !sc.isSuccess() ) return false;
365  if ( hist ) delete hist;
366  return true;
367 }
368 // ============================================================================
369 AIDA::IHistogram1D* HistogramSvc::book
370 (DataObject* pPar, CSTR rel, CSTR title, DBINS(x))
371 {
372  if ( m_defs1D.empty () )
373  { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
374  std::string hn = histoAddr ( pPar , rel ) ;
375  Histo1DMap::const_iterator ifound = m_defs1D.find( hn ) ;
376  if ( m_defs1D.end() == ifound )
377  { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
378  if (msgLevel(MSG::DEBUG)) {
379  MsgStream log ( msgSvc() , name() ) ;
380  log << MSG::DEBUG
381  << " Redefine the parameters for the histogram '" + hn + "' to be "
382  << ifound->second
383  << endmsg;
384  }
385  m_mods1D.insert ( hn ) ;
386  return i_book ( pPar , rel , ifound -> second.title () ,
388  ( ifound -> second.title () ,
389  ifound -> second.bins () ,
390  ifound -> second.lowEdge () ,
391  ifound -> second.lowEdge () ) ) ;
392 }
393 // ============================================================================
394 // constructor
395 // ============================================================================
397  : base_class(nam, svc)
398  , m_defs1D ()
399  , m_mods1D ()
400 {
401  // Properties can be declared here
402  m_rootName = "/stat";
403  m_rootCLID = CLID_DataObject;
404  declareProperty ( "Input", m_input);
405  declareProperty ( "Predefined1DHistos" , m_defs1D ,
406  "Histograms with predefined parameters" ) ;
407  // update handler
408  Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
410 
411 }
412 // ============================================================================
413 // handler to be invoked for updating property m_defs1D
414 // ============================================================================
415 namespace
416 {
417  inline size_t removeLeading
418  ( HistogramSvc::Histo1DMap& m , const std::string& lead = "/stat/")
419  {
420  for ( HistogramSvc::Histo1DMap::iterator it = m.begin() ;
421  m.end() != it ; ++it )
422  {
423  if ( 0 == it->first.find ( lead ) )
424  {
425  std::string addr = std::string( it->first , lead.size() ) ;
426  Gaudi::Histo1DDef hdef = it->second ;
427  m.erase ( it ) ; // remove
428  m[addr] = hdef ; // insert
429  return 1 + removeLeading ( m , lead ) ; // return
430  }
431  }
432  return 0 ;
433  }
434 }
435 // ============================================================================
437 {
438  // check and remove the leading '/stat/'
439  removeLeading ( m_defs1D , "/stat/" ) ;
440 }
441 // ============================================================================
442 // finalize the service
444 {
445  if ( !m_mods1D.empty() )
446  {
447  MsgStream log ( msgSvc () , name () ) ;
448  if (msgLevel(MSG::DEBUG))
449  log << MSG::DEBUG
450  << " Substituted histograms #" << m_mods1D.size() << " : " << endmsg;
451  for ( std::set<std::string>::const_iterator ih = m_mods1D.begin() ;
452  m_mods1D.end() != ih ; ++ih )
453  {
454  if (msgLevel(MSG::DEBUG))
455  log << MSG::DEBUG << " Path='" << (*ih) << "'" ;
456  Histo1DMap::const_iterator im = m_defs1D.find( *ih ) ;
457  if ( m_defs1D.end() != im ) { log << " " << im->second ; }
458  }
459  m_mods1D.clear() ;
460  }
461  return DataSvc::finalize () ;
462 }
463 // ============================================================================
464 // The END
465 // ============================================================================