00001 #include "RootIOSvc/RootInputFile.h"
00002 #include "RootIOSvc/RootIOBaseObject.h"
00003 #include "RootIOSvc/RootIOUserData.h"
00004 #include "RootIOSvc/RootIOUserDataProxy.h"
00005
00006 #include "TFile.h"
00007 #include "TTree.h"
00008 #include "TLeaf.h"
00009 #include "TDirectory.h"
00010 #include "TKey.h"
00011 #include "TIterator.h"
00012
00013 #include <string>
00014 #include <vector>
00015
00016
00017 static void handle_user_data(TTree* tree, const std::string& path)
00018 {
00019 TObjArray* branches = tree->GetListOfBranches();
00020 size_t nbranches = branches->GetEntries();
00021
00022 Dyb::MsgStreamMember log("RootInputFile::handle_user_data");
00023 log << MSG::DEBUG << "Found Tree (nBranches=" << nbranches
00024 << ") at path: " << path << endreq;
00025
00026
00027
00028 std::vector<TBranch*> known_unknowns, unknown_unknowns;
00029 for (size_t ind=0; ind<nbranches; ++ind) {
00030
00031 TBranch* branch = static_cast<TBranch*>(branches->At(ind));
00032 TLeaf* leaf = static_cast<TLeaf*>(branch->GetListOfLeaves()->At(0));
00033
00034 log << MSG::DEBUG << "\tCheckingName: "
00035 << branch->GetName()
00036 << " (" << leaf->GetTypeName() << ")"
00037 << endreq;
00038
00039
00040 std::string type = leaf->GetTypeName();
00041 if (type == "Int_t" || type == "Float_t") {
00042 log << MSG::DEBUG << "\t\tlikely branch: \""
00043 << branch->GetName() << "\"" << endreq;
00044 unknown_unknowns.push_back(branch);
00045 }
00046 else {
00047 TClass c(type.c_str());
00048 if (c.InheritsFrom("RootIOBaseObject")) {
00049 known_unknowns.push_back(branch);
00050 }
00051 else {
00052 log << MSG::DEBUG << "\t\tlikely branch: \""
00053 << branch->GetName() << "\"" << endreq;
00054 unknown_unknowns.push_back(branch);
00055 }
00056 }
00057 }
00058
00059 RootIOUserData ud;
00060 RootIOUserData::ProxyCollection& proxies = ud.input(path);
00061
00062 for (size_t ind=0; ind<unknown_unknowns.size(); ++ind) {
00063 TBranch* branch = unknown_unknowns[ind];
00064
00065 std::string className = branch->ClassName();
00066 TLeaf* leaf = static_cast<TLeaf*>(branch->GetListOfLeaves()->At(0));
00067
00068 char* addr = 0;
00069 if (className == "TBranchElement") {
00070 addr = *((char**)(branch->GetAddress()));
00071 }
00072 else {
00073 addr = (char*)(leaf->GetValuePointer());
00074 }
00075
00076 std::string branchName = branch->GetName();
00077
00078 RootIOUserDataProxy* udp = proxies[branchName];
00079 if (!udp) {
00080 std::string branchType = leaf->GetTypeName();
00081 udp = new RootIOUserDataProxy(branchName,branchType,addr);
00082 proxies[branchName] = udp;
00083 }
00084 else {
00085 udp->resetAddress(addr);
00086 }
00087
00088 }
00089
00090 }
00091
00092
00093 static void process_directory(TDirectory* dir, std::vector<std::string>& ret)
00094 {
00095 Dyb::MsgStreamMember log("RootInputFile::TreePaths");
00096
00097 TList* keys = dir->GetListOfKeys();
00098 TIter root_sucks(keys);
00099 TKey* key=0;
00100 while ((key = (TKey*)root_sucks())) {
00101 std::string dirpath = dir->GetPath();
00102 dirpath = dirpath.substr(dirpath.rfind(":")+1);
00103
00104 TObject* obj = key->ReadObj();
00105
00106 TDirectory* isDir = dynamic_cast<TDirectory*>(obj);
00107 if (isDir) {
00108 process_directory(isDir,ret);
00109 continue;
00110 }
00111 TTree* isTree = dynamic_cast<TTree*>(obj);
00112 if (isTree) {
00113 std::string path = "/";
00114
00115 if(dirpath != "/")
00116 path = dirpath + "/";
00117 path += isTree->GetName();
00118 ret.push_back(path);
00119 continue;
00120 }
00121
00122 log << MSG::WARNING
00123 << "unexpected object " << obj->GetName()
00124 << " of type " << obj->ClassName()
00125 << " found in directory " << dirpath << endreq;
00126 }
00127 }
00128
00129 std::vector<std::string> RootInputFile::TreePaths(const std::string& filename)
00130 {
00131 std::vector<std::string> ret;
00132
00133
00134 TFile* f = TFile::Open(filename.c_str(),"READ");
00135 if (!f->IsOpen()) {
00136 std::cerr << "File " << filename << " can not be opened for reading\n";
00137 return ret;
00138 }
00139
00140
00141 process_directory(f,ret);
00142 return ret;
00143 }
00144
00145
00146
00147
00148
00149 static int find_uniq(TBranch* branch)
00150 {
00151 static std::string name("RootIOBaseObject");
00152
00153
00154
00155 if (branch->GetName() == name) {
00156 TBranch* brID = branch->FindBranch("clID");
00157 RootIOBaseObject riobo;
00158 brID->SetAddress(&riobo);
00159 brID->GetEntry(0);
00160 return riobo.clID;
00161 }
00162
00163 TObjArray* branches = branch->GetListOfBranches();
00164 TIter root_sucks(branches);
00165 branch=0;
00166 while ((branch = (TBranch*)root_sucks())) {
00167 int ret = find_uniq(branch);
00168 if (ret) return ret;
00169 }
00170 return 0;
00171 }
00172
00173 int RootInputFile::TestForObject(const std::string& filename,
00174 const std::string& treepath,
00175 const std::string& branchname)
00176 {
00177 Dyb::MsgStreamMember log("RootInputFile::TestForTObject");
00178
00179
00180 TFile *f = TFile::Open(filename.c_str(),"READ");
00181 if (!f->IsOpen()) {
00182 log << MSG::ERROR
00183 << "File " << filename
00184 << " can not be opened for reading"
00185 << endreq;
00186 return 0;
00187 }
00188 log << MSG::DEBUG << "File " << filename
00189 << " opened. will now get obj at treepath is " << treepath
00190 << endreq;
00191
00192 TObject* obj = 0;
00193 if (treepath.rfind('/') == 0) {
00194
00195 log << MSG::VERBOSE << "Try to get root-level tree. get obj at treepath "
00196 << treepath.substr(1).c_str() << endreq;
00197 obj = f->Get(treepath.substr(1).c_str());
00198 }
00199 else {
00200 log << MSG::VERBOSE << "Get obj at treepath " << treepath.c_str() << endreq;
00201 obj = f->Get(treepath.c_str());
00202 }
00203 if (!obj) {
00204 log << MSG::ERROR
00205 << "No object " << treepath
00206 << " in file " << filename << endreq;
00207 return 0;
00208 }
00209 log << MSG::DEBUG << "Got object at " << treepath << endreq;
00210
00211 TTree* tree = dynamic_cast<TTree*>(obj);
00212 if (!tree) {
00213 log << MSG::ERROR
00214 << "Object at " << treepath
00215 << " in file " << filename
00216 << " is not a TTree" << endreq;
00217 return 0;
00218 }
00219
00220
00221 int nentries = tree->GetEntries();
00222 if (!nentries) {
00223 log << MSG::ERROR
00224 << "Tree " << treepath
00225 << " in filename " << filename
00226 << " found, but no entries" << endreq;
00227 return 0;
00228 }
00229
00230
00231 TBranch* b = tree->GetBranch(branchname.c_str());
00232 if (!b) {
00233 log << MSG::ERROR
00234 << "Failed to get branch " << branchname << endreq;
00235 return 0;
00236 }
00237
00238
00239 int ret = find_uniq(b);
00240 f->Close();
00241 delete f;
00242 return ret;
00243 }
00244
00245
00246 RootInputFile::RootInputFile(const std::string& filename,
00247 const std::string& treepath,
00248 const std::string& branchname)
00249 : m_filename(filename)
00250 , m_treepath(treepath)
00251 , m_branchname(branchname)
00252 , m_file(0), m_tree(0)
00253 , m_entry(-1), m_entries(-1)
00254 , m_addr(0)
00255 , log("RootInputFile")
00256 {
00257 }
00258 RootInputFile::~RootInputFile()
00259 {
00260 }
00261
00262 bool RootInputFile::open()
00263 {
00264 if (!m_file) {
00265 log << MSG::DEBUG
00266 << "openning " << m_filename << " for " << m_treepath
00267 << endreq;
00268
00269 m_file = TFile::Open(m_filename.c_str(),"READ");
00270 }
00271 if (!m_tree) {
00272 std::string treepath = m_treepath;
00273
00274 if(treepath.rfind("/") == 0) treepath = treepath.substr(1);
00275 TObject* obj = m_file->Get(treepath.c_str());
00276 if (!obj) {
00277 log << MSG::ERROR << "open(): No such object at " << m_treepath
00278 << " in " << m_filename << endreq;
00279 return false;
00280 }
00281 m_tree = dynamic_cast<TTree*>(obj);
00282 if (!m_tree) {
00283 log << MSG::ERROR
00284 << "open(): Object at " << m_treepath
00285 << " in " << m_filename
00286 << " not a TTree\n";
00287 return false;
00288 }
00289 if (m_entries < 0) {
00290 m_entries = m_tree->GetEntries();
00291 }
00292 }
00293 if (!m_tree) return false;
00294
00295 handle_user_data(m_tree,m_treepath);
00296
00297 return true;
00298 }
00299
00300 bool RootInputFile::leave()
00301 {
00302 log << MSG::DEBUG
00303 << "leaving " << m_filename << " for " << m_treepath
00304 << endreq;
00305
00306
00307 if(m_file) {
00308 m_file->Close();
00309 delete m_file;
00310 m_file = 0;
00311 }
00312 m_tree = 0;
00313 m_addr = 0;
00314 m_entry = -1;
00315
00316 return true;
00317 }
00318
00319 int RootInputFile::entry()
00320 {
00321 return m_entry;
00322 }
00323
00324 bool RootInputFile::setEntry(int entry)
00325 {
00326 if (!this->open()) return false;
00327 if (entry >= m_entries) {
00328 log << MSG::ERROR << "setEntry("<<entry<<"): Entry too large"
00329 << endreq;
00330 return false;
00331 }
00332 m_entry = entry;
00333 return true;
00334 }
00335
00336
00337 bool RootInputFile::setAddr(void* addr)
00338 {
00339 if (addr == m_addr) return true;
00340 TBranch* b = m_tree->GetBranch(m_branchname.c_str());
00341 if (!b) {
00342 log << MSG::ERROR << "setAddr(): no such branch named "
00343 << m_branchname << endreq;
00344 return false;
00345 }
00346
00347 log << MSG::DEBUG
00348 << "setAddr("<<(void*)addr<<") for " << m_branchname << " in " << m_filename
00349 << endreq;
00350 b->SetAddress(addr);
00351 m_addr = addr;
00352 return true;
00353 }
00354
00355 bool RootInputFile::read(void* addr)
00356 {
00357 int nbytes = 0;
00358 return this->read(addr,nbytes);
00359 }
00360
00361 bool RootInputFile::read(void* addr, int &nbytes)
00362 {
00363 nbytes = 0;
00364 if (!this->open()) return false;
00365 if (m_entry < 0 || m_entry >= m_entries) {
00366 log << MSG::ERROR << "read(void*): Bad entry: " << m_entry << endreq;
00367 return false;
00368 }
00369
00370 if (!this->setAddr(addr)) return false;
00371
00372 log << MSG::DEBUG
00373 << "read("<<(void*)addr<<") entry=" << m_entry
00374 << " from file " << m_filename
00375 << " and branch " << m_branchname
00376 << endreq;
00377 nbytes = m_tree->GetEntry(m_entry);
00378 return nbytes > 0;
00379 }
00380
00381 int RootInputFile::entries()
00382 {
00383 if (m_entries < 0) {
00384 if (!this->open()) return 0;
00385 this->leave();
00386 }
00387 return m_entries;
00388 }
00389
00390 bool RootInputFile::next(int steps)
00391 {
00392 return this->setEntry(m_entry+steps);
00393 }
00394
00395 bool RootInputFile::beginning()
00396 {
00397 if (!this->open()) return false;
00398 m_entry = 0;
00399 return true;
00400 }
00401 bool RootInputFile::ending()
00402 {
00403 if (!this->open()) return false;
00404 m_entry = m_entries-1;
00405 return true;
00406 }
00407
00408
00409 bool RootInputFile::prev(int steps)
00410 {
00411 return this->setEntry(m_entry-steps);
00412 }
00413
00414
00415
00416
00417 RootInputFileList::RootInputFileList()
00418 : std::vector<RootInputFile*>()
00419 , m_index(-1)
00420 , log("RootInputFileList")
00421 {
00422 }
00423
00424 RootInputFileList::~RootInputFileList()
00425 {
00426 }
00427
00428 int RootInputFileList::index()
00429 {
00430 return m_index;
00431 }
00432
00433 RootInputFile* RootInputFileList::current()
00434 {
00435 if (m_index < 0 || m_index >= (int)size()) return 0;
00436 return (*this)[m_index];
00437 }
00438
00439 bool RootInputFileList::next()
00440 {
00441 if (m_index + 1 >= (int)size()) {
00442 log << MSG::WARNING << "next(): already at last file"
00443 << endreq;
00444 return false;
00445 }
00446 RootInputFile* rif = current();
00447 if (rif) rif->leave();
00448 ++m_index;
00449 rif = current();
00450 if (!rif) {
00451 log << MSG::ERROR
00452 << "next(): failed to make next file curren"
00453 << endreq;
00454 return false;
00455 }
00456 return true;
00457 }
00458
00459 bool RootInputFileList::last()
00460 {
00461 if (m_index+1 == (int)size()) return true;
00462 RootInputFile* rif = current();
00463 if (rif) rif->leave();
00464 m_index = (int)size() - 1;
00465 rif = current();
00466 if (!rif) {
00467 log << MSG::ERROR
00468 << "last(): falied to make last file current"
00469 << endreq;
00470 return false;
00471 }
00472 return true;
00473 }
00474
00475 bool RootInputFileList::prev()
00476 {
00477 if (m_index <= 0) {
00478 log << MSG::ERROR
00479 << "prev(): already at first file"
00480 << endreq;
00481 return false;
00482 }
00483 RootInputFile* rif = current();
00484 if (rif) rif->leave();
00485 --m_index;
00486 rif = current();
00487 if (!rif) {
00488 log << MSG::ERROR
00489 << "prev(): failed to make prev file curren"
00490 << endreq;
00491 return false;
00492 }
00493 return true;
00494 }
00495
00496
00497
00498 bool RootInputFileList::first()
00499 {
00500 if (!m_index) return true;
00501 RootInputFile* rif = current();
00502 if (rif) rif->leave();
00503 m_index = 0;
00504 rif = current();
00505 if (!rif) {
00506 log << MSG::ERROR
00507 << "first(): failed to make first file current"
00508 << endreq;
00509 return false;
00510 }
00511 return true;
00512 }
00513
00514 bool RootInputFileList::jump(int index)
00515 {
00516 if (m_index == index) return true;
00517 RootInputFile* rif = current();
00518 if (rif) rif->leave();
00519 m_index = index;
00520 rif = current();
00521 if (!rif) {
00522 log << MSG::ERROR
00523 << "goto("<<index<<") failed"
00524 << endreq;
00525 return false;
00526 }
00527 return true;
00528 }
00529
00530 int RootInputFileList::entriesBefore(int index)
00531 {
00532 if (index < 0 || index >= (int)size()) return -1;
00533
00534 int totEntries = 0;
00535 for (int ind = 0; ind < index; ++ind) {
00536 int entries = (*this)[ind]->entries();
00537 if (entries < 0) return -1;
00538 totEntries += entries;
00539 }
00540 return totEntries;
00541 }
00542