/search.css" rel="stylesheet" type="text/css"/> /search.js">
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

In This Package:

RootInputFile.cc
Go to the documentation of this file.
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 
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Fri May 16 2014 09:58:18 for RootIOSvc by doxygen 1.7.4