| # Gaudi Framework, version v22r2 |

Home |  | Generated: Tue May 10 2011

# 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   MsgStream log ( msgSvc() , name() ) ;
    00380   log << MSG::DEBUG
    00381       << " Redefine the parameters for the histogram '" + hn +"' to be "
    00382       << ifound->second
    00383       << endmsg ;
    00384   m_mods1D.insert ( hn ) ;
    00385   return i_book ( pPar , rel , ifound -> second.title   () ,
    00386                   Gaudi::createH1D
    00387                   ( ifound -> second.title   () ,
    00388                     ifound -> second.bins    () ,
    00389                     ifound -> second.lowEdge () ,
    00390                     ifound -> second.lowEdge () ) ) ;
    00391 }
    00392 // ============================================================================
    00393 // constructor
    00394 // ============================================================================
    00395 HistogramSvc::HistogramSvc(CSTR nam, ISvcLocator* svc)
    00396   : base_class(nam, svc)
    00397   , m_defs1D ()
    00398   , m_mods1D ()
    00399 {
    00400   // Properties can be declared here
    00401   m_rootName = "/stat";
    00402   m_rootCLID = CLID_DataObject;
    00403   declareProperty ( "Input",  m_input);
    00404   declareProperty ( "Predefined1DHistos" , m_defs1D ,
    00405                     "Histograms with predefined parameters" ) ;
    00406   // update handler
    00407   Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
    00408   p->declareUpdateHandler ( &HistogramSvc::update1Ddefs , this ) ;
    00409
    00410 }
    00411 // ============================================================================
    00412 // handler to be invoked for updating property m_defs1D
    00413 // ============================================================================
    00414 namespace
    00415 {
    00416   inline size_t removeLeading
    00417   ( HistogramSvc::Histo1DMap& m , const std::string& lead = "/stat/")
    00418   {
    00419     for ( HistogramSvc::Histo1DMap::iterator it = m.begin() ;
    00420           m.end() != it ; ++it )
    00421     {
    00422       if ( 0 == it->first.find ( lead ) )
    00423       {
    00424         std::string       addr = std::string( it->first , lead.size() ) ;
    00425         Gaudi::Histo1DDef hdef = it->second ;
    00426         m.erase ( it ) ;                            // remove
    00427         m[addr] = hdef ;                            // insert
    00428         return 1 + removeLeading ( m , lead ) ;     // return
    00429       }
    00430     }
    00431     return 0 ;
    00432   }
    00433 }
    00434 // ============================================================================
    00435 void HistogramSvc::update1Ddefs ( Property& )
    00436 {
    00437   // check and remove the leading '/stat/'
    00438   removeLeading  ( m_defs1D , "/stat/" ) ;
    00439 }
    00440 // ============================================================================
    00441 // finalize the service
    00442 StatusCode HistogramSvc::finalize     ()
    00443 {
    00444   if ( !m_mods1D.empty() )
    00445   {
    00446     MsgStream log ( msgSvc () , name () ) ;
    00447     log << MSG::DEBUG
    00448         << " Substituted histograms #" << m_mods1D.size() << " : " << endmsg ;
    00449     for ( std::set<std::string>::const_iterator ih = m_mods1D.begin() ;
    00450           m_mods1D.end() != ih ; ++ih )
    00451     {
    00452       log << MSG::DEBUG << " Path='" << (*ih) << "'" ;
    00453       Histo1DMap::const_iterator im = m_defs1D.find( *ih ) ;
    00454       if ( m_defs1D.end() != im ) { log << "  " << im->second ; }
    00455     }
    00456     m_mods1D.clear() ;
    00457   }
    00458   return DataSvc::finalize () ;
    00459 }
    00460 // ============================================================================
    00461 // The END
    00462 // ============================================================================

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines