Gaudi Framework, version v21r8

Home   Generated: 17 Mar 2010

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" << endmsg;
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 << endmsg;
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 << endmsg;
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 = this->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 << endmsg;
00252           return status;
00253         }
00254         pA->release();
00255       }
00256     }
00257   }
00258   log << MSG::ERROR << "Cannot add " << ident << " invalid filename!" << endmsg;
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." << endmsg;
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." << endmsg;
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: " << endmsg ;
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 << endmsg ;
00301     }
00302   }
00303   return status;
00304 }
00305 //------------------------------------------------------------------------------
00306 StatusCode HistogramSvc::reinitialize()   {
00307   return StatusCode::SUCCESS;
00308 }
00309 //------------------------------------------------------------------------------
00310 IHistogram1D* HistogramSvc::sliceX
00311 (CSTR name,const IHistogram2D& h,int idxY1,int idxY2) {
00312   std::pair<DataObject*,IHistogram1D*> o(0,0);
00313   try {
00314     int firstbin = Gaudi::Axis::toRootIndex(idxY1,h.yAxis().bins());
00315     int lastbin  = Gaudi::Axis::toRootIndex(idxY2,h.yAxis().bins());
00316     o = Gaudi::slice1DX(name, h, firstbin, lastbin);
00317   }
00318   catch ( ... ) {
00319     throw GaudiException("Cannot cast 2D histogram to H2D to create sliceX `"
00320                          + name + "'!", "HistogramSvc", StatusCode::FAILURE);
00321   }
00322   if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() )  {
00323     return o.second;
00324   }
00325   delete o.first;
00326   throw GaudiException("Cannot create sliceX `" + name + "' of 2D histogram!",
00327     "HistogramSvc", StatusCode::FAILURE);
00328 }
00329 //------------------------------------------------------------------------------
00330 IHistogram1D*
00331 HistogramSvc::sliceY(CSTR name,const IHistogram2D& h,int indexX1,int indexX2) {
00332   std::pair<DataObject*,IHistogram1D*> o(0,0);
00333   try {
00334     int firstbin = Gaudi::Axis::toRootIndex( indexX1, h.xAxis().bins() );
00335     int lastbin  = Gaudi::Axis::toRootIndex( indexX2, h.xAxis().bins() );
00336     o = Gaudi::slice1DY(name, h, firstbin, lastbin);
00337   }
00338   catch ( ... ) {
00339     throw GaudiException("Cannot create sliceY `"+name+"'!",
00340                          "HistogramSvc",StatusCode::FAILURE);
00341   }
00342   // name stands here for the fullPath of the histogram
00343   if ( o.first && registerObject(name,(IBaseHistogram*)o.second).isSuccess() )  {
00344     return o.second;
00345   }
00346   delete o.first;
00347   throw GaudiException("Cannot create sliceY `"+name+"' of 2D histogram!",
00348                         "HistogramSvc", StatusCode::FAILURE);
00349 }
00350 //------------------------------------------------------------------------------
00351 bool HistogramSvc::destroy( IBaseHistogram* hist ) {
00352   StatusCode sc = unregisterObject( dynamic_cast<IHistogram*>(hist) );
00353   if ( !sc.isSuccess() ) return false;
00354   if ( hist ) delete hist;
00355   return true;
00356 }
00357 // ============================================================================
00358 AIDA::IHistogram1D* HistogramSvc::book
00359 (DataObject* pPar, CSTR rel, CSTR title, DBINS(x))
00360 {
00361   if ( m_defs1D.empty () )
00362   { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
00363   std::string hn = histoAddr ( pPar , rel ) ;
00364   Histo1DMap::const_iterator ifound = m_defs1D.find( hn ) ;
00365   if ( m_defs1D.end() == ifound )
00366   { return i_book(pPar,rel,title,Gaudi::createH1D(title, BINS(x))); }
00367   MsgStream log ( msgSvc() , name() ) ;
00368   log << MSG::DEBUG
00369       << " Redefine the parameters for the histogram '" + hn +"' to be "
00370       << ifound->second
00371       << endmsg ;
00372   m_mods1D.insert ( hn ) ;
00373   return i_book ( pPar , rel , ifound -> second.title   () ,
00374                   Gaudi::createH1D
00375                   ( ifound -> second.title   () ,
00376                     ifound -> second.bins    () ,
00377                     ifound -> second.lowEdge () ,
00378                     ifound -> second.lowEdge () ) ) ;
00379 }
00380 // ============================================================================
00381 // constructor
00382 // ============================================================================
00383 HistogramSvc::HistogramSvc(CSTR nam, ISvcLocator* svc)
00384   : base_class(nam, svc)
00385   , m_defs1D ()
00386   , m_mods1D ()
00387 {
00388   // Properties can be declared here
00389   m_rootName = "/stat";
00390   m_rootCLID = CLID_DataObject;
00391   declareProperty ( "Input",  m_input);
00392   declareProperty ( "Predefined1DHistos" , m_defs1D ,
00393                     "Histograms with predefined parameters" ) ;
00394   // update handler
00395   Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
00396   p->declareUpdateHandler ( &HistogramSvc::update1Ddefs , this ) ;
00397 
00398 }
00399 // ============================================================================
00400 // handler to be invoked for updating property m_defs1D
00401 // ============================================================================
00402 namespace
00403 {
00404   inline size_t removeLeading
00405   ( HistogramSvc::Histo1DMap& m , const std::string& lead = "/stat/")
00406   {
00407     for ( HistogramSvc::Histo1DMap::iterator it = m.begin() ;
00408           m.end() != it ; ++it )
00409     {
00410       if ( 0 == it->first.find ( lead ) )
00411       {
00412         std::string       addr = std::string( it->first , lead.size() ) ;
00413         Gaudi::Histo1DDef hdef = it->second ;
00414         m.erase ( it ) ;                            // remove
00415         m[addr] = hdef ;                            // insert
00416         return 1 + removeLeading ( m , lead ) ;     // return
00417       }
00418     }
00419     return 0 ;
00420   }
00421 }
00422 // ============================================================================
00423 void HistogramSvc::update1Ddefs ( Property& )
00424 {
00425   // check and remove the leading '/stat/'
00426   removeLeading  ( m_defs1D , "/stat/" ) ;
00427 }
00428 // ============================================================================
00429 // finalize the service
00430 StatusCode HistogramSvc::finalize     ()
00431 {
00432   if ( !m_mods1D.empty() )
00433   {
00434     MsgStream log ( msgSvc () , name () ) ;
00435     log << MSG::DEBUG
00436         << " Substituted histograms #" << m_mods1D.size() << " : " << endmsg ;
00437     for ( std::set<std::string>::const_iterator ih = m_mods1D.begin() ;
00438           m_mods1D.end() != ih ; ++ih )
00439     {
00440       log << MSG::DEBUG << " Path='" << (*ih) << "'" ;
00441       Histo1DMap::const_iterator im = m_defs1D.find( *ih ) ;
00442       if ( m_defs1D.end() != im ) { log << "  " << im->second ; }
00443     }
00444     m_mods1D.clear() ;
00445   }
00446   return DataSvc::finalize () ;
00447 }
00448 // ============================================================================
00449 
00450 // ============================================================================
00451 // The END
00452 // ============================================================================

Generated at Wed Mar 17 18:06:44 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004