Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

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

Generated at Thu Jun 28 2012 23:27:16 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004