00001
00002
00003
00004
00005
00006
00007 #include <cstdlib>
00008 #include <stdexcept>
00009
00010
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
00022
00023 #include "HistogramSvc.h"
00024
00025
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
00070 if (obj[0] == SEPARATOR) {
00071
00072 if (!hObj->annotation().addItem("id", obj.substr(1)))
00073 hObj->annotation().setValue("id", obj.substr(1));
00074 }
00075 else {
00076
00077 if (!hObj->annotation().addItem("id", obj))
00078 hObj->annotation().setValue("id", obj);
00079 }
00080
00081 return DataSvc::registerObject(pPar,obj,__cast(hObj));
00082 }
00083
00084
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
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
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
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':
00221 case 'D':
00222 filename = (*i).value();
00223 break;
00224 case 'T':
00225 typ = (*i).value();
00226 break;
00227 default:
00228 break;
00229 }
00230 }
00231 if (typ.length() > 0) {
00232
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
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
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
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
00382
00383 HistogramSvc::HistogramSvc(CSTR nam, ISvcLocator* svc)
00384 : base_class(nam, svc)
00385 , m_defs1D ()
00386 , m_mods1D ()
00387 {
00388
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
00395 Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
00396 p->declareUpdateHandler ( &HistogramSvc::update1Ddefs , this ) ;
00397
00398 }
00399
00400
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 ) ;
00415 m[addr] = hdef ;
00416 return 1 + removeLeading ( m , lead ) ;
00417 }
00418 }
00419 return 0 ;
00420 }
00421 }
00422
00423 void HistogramSvc::update1Ddefs ( Property& )
00424 {
00425
00426 removeLeading ( m_defs1D , "/stat/" ) ;
00427 }
00428
00429
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
00452