| 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 "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     // Check the tree for branches besides ones made from a
00027     // RootIOBaseObject
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         // Let's do a little dance.  It's called, "find who we know".
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); // Outlander!
00045         }
00046         else {
00047             TClass c(type.c_str());
00048             if (c.InheritsFrom("RootIOBaseObject")) {
00049                 known_unknowns.push_back(branch); // I know you!
00050             }
00051             else {
00052                 log << MSG::DEBUG << "\t\tlikely branch: \"" 
00053                     << branch->GetName() << "\"" << endreq;
00054                 unknown_unknowns.push_back(branch); // Outlander!
00055             }
00056         }
00057     }
00058 
00059     RootIOUserData ud;          // get proxies for given stream
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(); // eg "TBranch"
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(); // eg "count"
00077 
00078         RootIOUserDataProxy* udp = proxies[branchName];
00079         if (!udp) {
00080             std::string branchType = leaf->GetTypeName(); // eg "Int_t"
00081             udp = new RootIOUserDataProxy(branchName,branchType,addr);
00082             proxies[branchName] = udp;
00083         }
00084         else {
00085             udp->resetAddress(addr);
00086         }
00087 
00088     } // loop over unknown unknowns
00089 
00090 }     // handle_user_data()
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())) { // infinite loop? ROOT does suck a lot!
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             // Catch trees in root directory
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     //std::cerr << "File " << filename << " openeded\n";
00140     
00141     process_directory(f,ret);
00142     return ret;
00143 }
00144 
00145 
00146 //#include <iostream>
00147 //using namespace std;
00148 
00149 static int find_uniq(TBranch* branch)
00150 {
00151     static std::string name("RootIOBaseObject");
00152 
00153     //cerr << "Checking branch " << branch->GetName() << std::endl;
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         // Catch root-level trees
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     //cerr << "Object is a TTree\n";
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     //cerr << "Tree has " << nentries << " entries\n";
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     //cerr << "search for uniq id" << std::endl;
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         // Catch top-level objects
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     // The opened file must be closed to avoid memory leak
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) {        // never opened this file
00384         if (!this->open()) return 0;
00385         this->leave();          // may not want to leave open long term, leave it as found it
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 // ----- RootInputFileList ----- //
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     // cound up entries up to but not including current index
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 
| Classes | Job Modules | Data Objects | Services | Algorithms | Tools | Packages | Directories | Tracs |

Generated on Mon Apr 11 20:18:19 2011 for RootIOSvc by doxygen 1.4.7