00001
00002 #ifdef __ICC
00003
00004
00005 #pragma warning(disable:2259)
00006 #endif
00007
00008
00009
00010
00011
00012 #include <cstdlib>
00013 #include <stdexcept>
00014
00015
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
00027
00028 #include "HistogramSvc.h"
00029
00030
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
00075 if (obj[0] == SEPARATOR) {
00076
00077 if (!hObj->annotation().addItem("id", obj.substr(1)))
00078 hObj->annotation().setValue("id", obj.substr(1));
00079 }
00080 else {
00081
00082 if (!hObj->annotation().addItem("id", obj))
00083 hObj->annotation().setValue("id", obj);
00084 }
00085
00086 return DataSvc::registerObject(pPar,obj,__cast(hObj));
00087 }
00088
00089
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
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
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
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':
00226 case 'D':
00227 filename = (*i).value();
00228 break;
00229 case 'T':
00230 typ = (*i).value();
00231 break;
00232 default:
00233 break;
00234 }
00235 }
00236 if (typ.length() > 0) {
00237
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
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
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
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
00387
00388 HistogramSvc::HistogramSvc(CSTR nam, ISvcLocator* svc)
00389 : base_class(nam, svc)
00390 , m_defs1D ()
00391 , m_mods1D ()
00392 {
00393
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
00400 Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
00401 p->declareUpdateHandler ( &HistogramSvc::update1Ddefs , this ) ;
00402
00403 }
00404
00405
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 ) ;
00420 m[addr] = hdef ;
00421 return 1 + removeLeading ( m , lead ) ;
00422 }
00423 }
00424 return 0 ;
00425 }
00426 }
00427
00428 void HistogramSvc::update1Ddefs ( Property& )
00429 {
00430
00431 removeLeading ( m_defs1D , "/stat/" ) ;
00432 }
00433
00434
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
00457