| # Gaudi Framework, version v20r4
Generated: 8 Jan 2009

# HistogramSvc.cpp

Go to the documentation of this file.

    00001 // $Id: HistogramSvc.cpp,v 1.28 2007/09/26 16:14:47 marcocle Exp $
    00002 // ============================================================================
    00003 // Include files
    00004 // ============================================================================
    00005 // STD&STL
    00006 // ============================================================================
    00007 #include <cstdlib>
    00008 #include <stdexcept>
    00009 // ============================================================================
    00010 // GaudiKernel
    00011 // ============================================================================
    00012 #include "GaudiKernel/xtoa.h"
    00013 #include "GaudiKernel/Property.h"
    00014 #include "GaudiKernel/Tokenizer.h"
    00015 #include "GaudiKernel/MsgStream.h"
    00016 #include "GaudiKernel/SvcFactory.h"
    00017 #include "GaudiKernel/DataObject.h"
    00018 #include "GaudiKernel/IConversionSvc.h"
    00019 #include "GaudiKernel/GenericAddress.h"
    00020 // ============================================================================
    00021 // Local
    00022 // ============================================================================
    00023 #include "HistogramSvc.h"
    00024 // ============================================================================
    00025 // Instantiation of a factory class used by clients
    00026 DECLARE_SERVICE_FACTORY(HistogramSvc)
    00027 // ============================================================================
    00028 using namespace AIDA;
    00029 // ============================================================================
    00030 namespace
    00031 {
    00032   // ==========================================================================
    00033   inline std::string histoAddr
    00034   ( const std::string& name)
    00035   {
    00036     if ( 0 == name.find ( "/stat/" ) ){ return std::string( name , 6 ) ; }
    00037     return name ;
    00038   }
    00039   // ==========================================================================
    00040   inline std::string histoAddr
    00041   ( const DataObject*  obj ,
    00042     const std::string& rel )
    00043   {
    00044     if ( 0 == obj      ) { return rel  ; }
    00045     IRegistry* reg = obj->registry() ;
    00046     if ( 0 == reg      ) { return rel  ; }
    00047     const std::string& name = reg->identifier() ;
    00048     //
    00049     if ( rel  .empty() ) { return histoAddr ( name ) ; }
    00050     if ( '/' == name[name.size()-1] ||
    00051          '/' == rel[0] ) { return histoAddr ( name + rel ) ; }
    00052     return histoAddr ( name + "/" + rel ) ;
    00053   }
    00054   // ==========================================================================
    00055 }
    00056 //------------------------------------------------------------------------------
    00057 std::string HistogramSvc::_STR(int i)  {
    00058   char txt[32];
    00059   return _itoa(i, txt, 10);
    00060 }
    00061 //------------------------------------------------------------------------------
    00062 StatusCode HistogramSvc::registerObject(CSTR full, IBaseHistogram* obj)  {
    00063   std::pair<std::string,std::string> split=i_splitPath(full);
    00064   return registerObject(split.first, split.second, obj);
    00065 }
    00066 //------------------------------------------------------------------------------
    00067 StatusCode HistogramSvc::registerObject
    00068 (DataObject* pPar,CSTR obj,IBaseHistogram* hObj) {
    00069   // Set the hstogram id
    00070   if (obj[0] == SEPARATOR)    {
    00071     // hObj->setTitle(obj.substr(1) + "|" + hObj->title());
    00072     if (!hObj->annotation().addItem("id", obj.substr(1)))
    00073       hObj->annotation().setValue("id", obj.substr(1));
    00074   }
    00075   else {
    00076     // hObj->setTitle(obj + "|" + hObj->title());
    00077     if (!hObj->annotation().addItem("id", obj))
    00078       hObj->annotation().setValue("id", obj);
    00079   }
    00080   // Register the hstogram in the hstogram data store
    00081   return DataSvc::registerObject(pPar,obj,__cast(hObj));
    00082 }
    00083
    00084 // Helper for 2D projections
    00085 AIDA::IHistogram2D*
    00086 HistogramSvc::i_project(CSTR nameAndTitle,const IHistogram3D& h, CSTR dir)  {
    00087   TH3D *h3d = Gaudi::getRepresentation<IHistogram3D,TH3D>(h);
    00088   if ( h3d )  {
    00089     TH2D *h2d = dynamic_cast<TH2D*>(h3d->Project3D(dir.c_str()));
    00090     if ( h2d )  {
    00091       std::pair<DataObject*,H2D*> r=Gaudi::createH2D(h2d);
    00092       if ( r.second && registerObject(nameAndTitle,r.second).isSuccess() )  {
    00093         return r.second;
    00094       }
    00095     }
    00096   }
    00097   return 0;
    00098 }
    00099
    00100 //------------------------------------------------------------------------------
    00101 // ASCII output
    00102 //------------------------------------------------------------------------------
    00103 std::ostream& HistogramSvc::print(IBaseHistogram* h, std::ostream& s) const  {
    00104   Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
    00105   if(0 != b) return b->print(s);
    00106   MsgStream log(msgSvc(), name());
    00107   log << MSG::ERROR << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
    00108       << endmsg;
    00109   return s;
    00110 }
    00111 //------------------------------------------------------------------------------
    00112 std::ostream& HistogramSvc::write(IBaseHistogram* h, std::ostream& s) const  {
    00113   Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
    00114   if(0 != b) return b->write(s);
    00115   MsgStream log(msgSvc(), name());
    00116   log << MSG::ERROR << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
    00117       << endmsg;
    00118   return s;
    00119 }
    00120 //------------------------------------------------------------------------------
    00121 int HistogramSvc::write(IBaseHistogram* h, const char* file_name) const  {
    00122   Gaudi::HistogramBase* b = dynamic_cast<Gaudi::HistogramBase*>(h);
    00123   if(0 != b) return b->write(file_name);
    00124   MsgStream log(msgSvc(), name());
    00125   log << MSG::ERROR << "Unknown histogram type: Cannot cast to Gaudi::HistogramBase."
    00126       << endmsg;
    00127   return 0;
    00128 }
    00129 //------------------------------------------------------------------------------
    00130 std::pair<std::string,std::string> HistogramSvc::i_splitPath(CSTR full)   {
    00131   std::string tmp = full;
    00132   if (tmp[0] != SEPARATOR)    {
    00133     tmp.insert(tmp.begin(), SEPARATOR);
    00134     tmp.insert(tmp.begin(), m_rootName.begin(), m_rootName.end());
    00135   }
    00136   // Remove trailing "/" from newPath if it exists
    00137   if (tmp.rfind(SEPARATOR) == tmp.length()-1) {
    00138     tmp.erase(tmp.rfind(SEPARATOR),1);
    00139   }
    00140   int sep = tmp.rfind(SEPARATOR);
    00141   return std::pair<std::string,std::string>
    00142     (tmp.substr(0,sep),tmp.substr(sep,tmp.length()-sep));
    00143 }
    00144 //------------------------------------------------------------------------------
    00145 DataObject* HistogramSvc::createPath(CSTR newPath)  {
    00146   std::string tmpPath = newPath;
    00147   if (tmpPath[0] != SEPARATOR)    {
    00148     tmpPath.insert(tmpPath.begin(), SEPARATOR);
    00149     tmpPath.insert(tmpPath.begin(), m_rootName.begin(), m_rootName.end());
    00150   }
    00151   // Remove trailing "/" from newPath if it exists
    00152   if (tmpPath.rfind(SEPARATOR) == tmpPath.length()-1) {
    00153     tmpPath.erase(tmpPath.rfind(SEPARATOR),1);
    00154   }
    00155   DataObject* pObject = 0;
    00156   StatusCode sc = DataSvc::findObject(tmpPath, pObject);
    00157   if(sc.isSuccess()) {
    00158     return pObject;
    00159   }
    00160   int sep = tmpPath.rfind(SEPARATOR);
    00161   std::string rest(tmpPath, sep+1, tmpPath.length()-sep);
    00162   std::string subPath(tmpPath, 0, sep);
    00163   if(0 != sep) {
    00164     createPath(subPath);
    00165   }
    00166   else {
    00167     MsgStream log(msgSvc(), name());
    00168     log << MSG::ERROR << "Unable to create the histogram path" << endreq;
    00169     return 0;
    00170   }
    00171   pObject = createDirectory(subPath, rest);
    00172   return pObject;
    00173 }
    00174 //------------------------------------------------------------------------------
    00175 DataObject* HistogramSvc::createDirectory(CSTR parentDir,CSTR subDir) {
    00176   DataObject*  directory = new DataObject();
    00177   if (0 != directory)  {
    00178     DataObject* pnode;
    00179     StatusCode status = DataSvc::retrieveObject(parentDir, pnode);
    00180     if(status.isSuccess()) {
    00181       status = DataSvc::registerObject(pnode, subDir, directory);
    00182       if (!status.isSuccess())   {
    00183         MsgStream log(msgSvc(), name());
    00184         log << MSG::ERROR << "Unable to create the histogram directory: "
    00185                           << parentDir << "/" << subDir << endreq;
    00186         delete directory;
    00187         return 0;
    00188       }
    00189     }
    00190     else {
    00191       MsgStream log(msgSvc(), name());
    00192       log << MSG::ERROR << "Unable to create the histogram directory: "
    00193                         << parentDir << "/" << subDir << endreq;
    00194       delete directory;
    00195       return 0;
    00196     }
    00197   }
    00198   return directory;
    00199 }
    00200 //------------------------------------------------------------------------------
    00201 HistogramSvc::~HistogramSvc()   {
    00202   setDataLoader( 0 ).ignore();
    00203   clearStore().ignore();
    00204 }
    00205 //------------------------------------------------------------------------------
    00206 StatusCode HistogramSvc::connectInput(CSTR ident) {
    00207   MsgStream log (msgSvc(), name());
    00208   DataObject* pO = 0;
    00209   StatusCode status = findObject(m_rootName, pO);
    00210   if (status.isSuccess())   {
    00211     Tokenizer tok(true);
    00212     std::string::size_type loc = ident.find(" ");
    00213     std::string filename, auth, svc = "", typ = "";
    00214     std::string logname = ident.substr(0,loc);
    00215     tok.analyse(ident.substr(loc+1,ident.length()), " ", "", "", "=", "'", "'");
    00216     for (Tokenizer::Items::iterator i = tok.items().begin();
    00217          i != tok.items().end(); i++) {
    00218       CSTR tag = (*i).tag();
    00219       switch(::toupper(tag[0]))   {
    00220       case 'F':   // FILE='<file name>'
    00221       case 'D':   // DATAFILE='<file name>'
    00222         filename = (*i).value();
    00223         break;
    00224       case 'T':   // TYP='<HBOOK,ROOT,OBJY,...>'
    00225         typ = (*i).value();
    00226         break;
    00227       default:
    00228         break;
    00229       }
    00230     }
    00231     if (typ.length() > 0)    {
    00232       // Now add the registry entry to the store
    00233       std::string entryname = m_rootName;
    00234       entryname += '/';
    00235       entryname += logname;
    00236       GenericAddress* pA = 0;
    00237       switch(::toupper(typ[0])) {
    00238       case 'H':
    00239         pA=new GenericAddress(HBOOK_StorageType,CLID_StatisticsFile,
    00240                               filename,entryname,0,'O');
    00241         break;
    00242       case 'R':
    00243         pA=new GenericAddress(ROOT_StorageType,CLID_StatisticsFile,
    00244                               filename,entryname,0,'O');
    00245         break;
    00246       }
    00247       if (0 != pA)    {
    00248         status = registerAddress(pO, logname, pA);
    00249         if (status.isSuccess())    {
    00250           log << MSG::INFO << "Added stream file:" << filename
    00251               << " as " << logname << endreq;
    00252           return status;
    00253         }
    00254         pA->release();
    00255       }
    00256     }
    00257   }
    00258   log << MSG::ERROR << "Cannot add " << ident << " invalid filename!" << endreq;
    00259   return StatusCode::FAILURE;
    00260 }
    00261 //------------------------------------------------------------------------------
    00262 StatusCode HistogramSvc::initialize()   {
    00263   MsgStream log(msgSvc(), name());
    00264   StatusCode status = DataSvc::initialize();
    00265   // Set root object
    00266   if (status.isSuccess()) {
    00267     DataObject* rootObj = new DataObject();
    00268     status = setRoot("/stat", rootObj);
    00269     if (!status.isSuccess()) {
    00270       log << MSG::ERROR << "Unable to set hstogram data store root." << endreq;
    00271       delete rootObj;
    00272       return status;
    00273     }
    00274     IConversionSvc* svc = 0;
    00275     status = service("HistogramPersistencySvc",svc,true);
    00276     if ( status.isSuccess() )   {
    00277       setDataLoader( svc ).ignore();
    00278       svc->release();
    00279     }
    00280     else  {
    00281       log << MSG::ERROR << "Could not find HistogramPersistencySvc." << endreq;
    00282       return status;
    00283     }
    00284     // Connect all input streams (if any)
    00285     for (DBaseEntries::iterator j = m_input.begin(); j != m_input.end(); j++)    {
    00286       status = connectInput(*j);
    00287       if (!status.isSuccess())  {
    00288         return status;
    00289       }
    00290     }
    00291   }
    00292   if ( !m_defs1D.empty() )
    00293   {
    00294     log << MSG::INFO << " Predefined 1D-Histograms: " << endreq ;
    00295     for ( Histo1DMap::const_iterator ih = m_defs1D.begin() ;
    00296           m_defs1D.end() != ih ; ++ih )
    00297     {
    00298       log << MSG::INFO
    00299           << " Path='"       << ih->first  << "'"
    00300           << " Description " << ih->second << endreq ;
    00301     }
    00302   }
    00303   return status;
    00304 }
    00305 //------------------------------------------------------------------------------
    00306 StatusCode HistogramSvc::reinitialize()   {
    00307   return StatusCode::SUCCESS;
    00308 }
    00309 //------------------------------------------------------------------------------
    00310 StatusCode HistogramSvc::queryInterface
    00311 (const InterfaceID& riid,void** ppvInterface)  {
    00312   if(riid == IID_IHistogramSvc)  {
    00313     *ppvInterface = static_cast<IHistogramSvc*>(this);
    00314     addRef();
    00315     return StatusCode::SUCCESS;
    00316   }
    00317   // Interface is not directly availible: try out a base class
    00318   return DataSvc::queryInterface(riid, ppvInterface);
    00319 }
    00320 //------------------------------------------------------------------------------
    00321 IHistogram1D* HistogramSvc::sliceX
    00322 (CSTR name,const IHistogram2D& h,int idxY1,int idxY2) {
    00323   std::pair<DataObject*,IHistogram1D*> o(0,0);
    00324   try {
    00325     int firstbin = Gaudi::Axis::toRootIndex(idxY1,h.yAxis().bins());
    00326     int lastbin  = Gaudi::Axis::toRootIndex(idxY2,h.yAxis().bins());
    00327     o = Gaudi::slice1DX(name, h, firstbin, lastbin);
    00328   }
    00329   catch ( ... ) {
    00330     throw GaudiException("Cannot cast 2D histogram to H2D to create sliceX `"
    00331                          + name + "'!", "HistogramSvc", StatusCode::FAILURE);
    00332   }
    00333   if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() )  {
    00334     return o.second;
    00335   }
    00336   delete o.first;
    00337   throw GaudiException("Cannot create sliceX `" + name + "' of 2D histogram!",
    00338     "HistogramSvc", StatusCode::FAILURE);
    00339 }
    00340 //------------------------------------------------------------------------------
    00341 IHistogram1D*
    00342 HistogramSvc::sliceY(CSTR name,const IHistogram2D& h,int indexX1,int indexX2) {
    00343   std::pair<DataObject*,IHistogram1D*> o(0,0);
    00344   try {
    00345     int firstbin = Gaudi::Axis::toRootIndex( indexX1, h.xAxis().bins() );
    00346     int lastbin  = Gaudi::Axis::toRootIndex( indexX2, h.xAxis().bins() );
    00347     o = Gaudi::slice1DY(name, h, firstbin, lastbin);
    00348   }
    00349   catch ( ... ) {
    00350     throw GaudiException("Cannot create sliceY `"+name+"'!",
    00351                          "HistogramSvc",StatusCode::FAILURE);
    00352   }
    00353   // name stands here for the fullPath of the histogram
    00354   if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() )  {
    00355     return o.second;
    00356   }
    00357   delete o.first;
    00358   throw GaudiException("Cannot create sliceY `"+name+"' of 2D histogram!",
    00359                         "HistogramSvc", StatusCode::FAILURE);
    00360 }
    00361 //------------------------------------------------------------------------------
    00362 bool HistogramSvc::destroy( IBaseHistogram* hist ) {
    00363   StatusCode sc = unregisterObject( dynamic_cast<IHistogram*>(hist) );
    00364   if ( !sc.isSuccess() ) return false;
    00365   if ( hist ) delete hist;
    00366   return true;
    00367 }
    00368 // ============================================================================
    00369 AIDA::IHistogram1D* HistogramSvc::book
    00370 (DataObject* pPar, CSTR rel, CSTR title, DBINS(x))
    00371 {
    00372   if ( m_defs1D.empty () )
    00373   { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
    00374   std::string hn = histoAddr ( pPar , rel ) ;
    00375   Histo1DMap::const_iterator ifound = m_defs1D.find( hn ) ;
    00376   if ( m_defs1D.end() == ifound )
    00377   { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
    00378   MsgStream log ( msgSvc() , name() ) ;
    00379   log << MSG::DEBUG
    00380       << " Redefine the parameters for the histogram '" + hn +"' to be "
    00381       << ifound->second
    00382       << endreq ;
    00383   m_mods1D.insert ( hn ) ;
    00384   return i_book ( pPar , rel , ifound -> second.title   () ,
    00385                   Gaudi::createH1D
    00386                   ( ifound -> second.title   () ,
    00387                     ifound -> second.bins    () ,
    00388                     ifound -> second.lowEdge () ,
    00389                     ifound -> second.lowEdge () ) ) ;
    00390 }
    00391 // ============================================================================
    00392 // constructor
    00393 // ============================================================================
    00394 HistogramSvc::HistogramSvc(CSTR nam, ISvcLocator* svc)
    00395   : DataSvc(nam, svc)
    00396   , m_defs1D ()
    00397   , m_mods1D ()
    00398 {
    00399   // Properties can be declared here
    00400   m_rootName = "/stat";
    00401   m_rootCLID = CLID_DataObject;
    00402   declareProperty ( "Input",  m_input);
    00403   declareProperty ( "Predefined1DHistos" , m_defs1D ,
    00404                     "Histograms with predefined parameters" ) ;
    00405   // update handler
    00406   Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
    00407   p->declareUpdateHandler ( &HistogramSvc::update1Ddefs , this ) ;
    00408
    00409 }
    00410 // ============================================================================
    00411 // handler to be invoked for updating property m_defs1D
    00412 // ============================================================================
    00413 namespace
    00414 {
    00415   inline size_t removeLeading
    00416   ( HistogramSvc::Histo1DMap& m , const std::string& lead = "/stat/")
    00417   {
    00418     for ( HistogramSvc::Histo1DMap::iterator it = m.begin() ;
    00419           m.end() != it ; ++it )
    00420     {
    00421       if ( 0 == it->first.find ( lead ) )
    00422       {
    00423         std::string       addr = std::string( it->first , lead.size() ) ;
    00424         Gaudi::Histo1DDef hdef = it->second ;
    00425         m.erase ( it ) ;                            // remove
    00426         m[addr] = hdef ;                            // insert
    00427         return 1 + removeLeading ( m , lead ) ;     // return
    00428       }
    00429     }
    00430     return 0 ;
    00431   }
    00432 }
    00433 // ============================================================================
    00434 void HistogramSvc::update1Ddefs ( Property& )
    00435 {
    00436   // check and remove the leading '/stat/'
    00437   removeLeading  ( m_defs1D , "/stat/" ) ;
    00438 }
    00439 // ============================================================================
    00440 // finalize the service
    00441 StatusCode HistogramSvc::finalize     ()
    00442 {
    00443   if ( !m_mods1D.empty() )
    00444   {
    00445     MsgStream log ( msgSvc () , name () ) ;
    00446     log << MSG::DEBUG
    00447         << " Substituted histograms #" << m_mods1D.size() << " : " << endreq ;
    00448     for ( std::set<std::string>::const_iterator ih = m_mods1D.begin() ;
    00449           m_mods1D.end() != ih ; ++ih )
    00450     {
    00451       log << MSG::DEBUG << " Path='" << (*ih) << "'" ;
    00452       Histo1DMap::const_iterator im = m_defs1D.find( *ih ) ;
    00453       if ( m_defs1D.end() != im ) { log << "  " << im->second ; }
    00454     }
    00455     m_mods1D.clear() ;
    00456   }
    00457   return DataSvc::finalize () ;
    00458 }
    00459 // ============================================================================
    00460
    00461
    00462 // ============================================================================
    00463 // The END
    00464 // ============================================================================