00001
00002 #ifdef __ICC
00003
00004
00005 #pragma warning(disable:2259)
00006 #endif
00007 #ifdef WIN32
00008
00009
00010
00011 #pragma warning(disable:4996)
00012 #endif
00013
00014
00015
00016
00017
00018 #include <cstdlib>
00019 #include <stdexcept>
00020 #include <sstream>
00021
00022
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
00034
00035 #include "HistogramSvc.h"
00036
00037
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
00082 if (obj[0] == SEPARATOR) {
00083
00084 if (!hObj->annotation().addItem("id", obj.substr(1)))
00085 hObj->annotation().setValue("id", obj.substr(1));
00086 }
00087 else {
00088
00089 if (!hObj->annotation().addItem("id", obj))
00090 hObj->annotation().setValue("id", obj);
00091 }
00092
00093 return DataSvc::registerObject(pPar,obj,__cast(hObj));
00094 }
00095
00096
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
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
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
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':
00233 case 'D':
00234 filename = (*i).value();
00235 break;
00236 case 'T':
00237 typ = (*i).value();
00238 break;
00239 default:
00240 break;
00241 }
00242 }
00243 if (typ.length() > 0) {
00244
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
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
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
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
00396
00397 HistogramSvc::HistogramSvc(CSTR nam, ISvcLocator* svc)
00398 : base_class(nam, svc)
00399 , m_defs1D ()
00400 , m_mods1D ()
00401 {
00402
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
00409 Property* p = Gaudi::Utils::getProperty ( this , "Predefined1DHistos" ) ;
00410 p->declareUpdateHandler ( &HistogramSvc::update1Ddefs , this ) ;
00411
00412 }
00413
00414
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 ) ;
00429 m[addr] = hdef ;
00430 return 1 + removeLeading ( m , lead ) ;
00431 }
00432 }
00433 return 0 ;
00434 }
00435 }
00436
00437 void HistogramSvc::update1Ddefs ( Property& )
00438 {
00439
00440 removeLeading ( m_defs1D , "/stat/" ) ;
00441 }
00442
00443
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
00466