| # Gaudi Framework, version v21r10p1 |

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