![]() |
|
|
Generated: 8 Jan 2009 |
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 // ============================================================================