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