00001 #include "RootTree.h"
00002 #include "RootDelayedReader.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/Utilities/interface/Exception.h"
00005 #include "DataFormats/Provenance/interface/BranchDescription.h"
00006 #include "InputFile.h"
00007 #include "TTree.h"
00008 #include "TTreeIndex.h"
00009 #include "TTreeCache.h"
00010
00011 #include <iostream>
00012
00013 namespace edm {
00014 namespace {
00015 TBranch* getAuxiliaryBranch(TTree* tree, BranchType const& branchType) {
00016 TBranch* branch = tree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
00017 if (branch == 0) {
00018 branch = tree->GetBranch(BranchTypeToAuxBranchName(branchType).c_str());
00019 }
00020 return branch;
00021 }
00022 TBranch* getProductProvenanceBranch(TTree* tree, BranchType const& branchType) {
00023 TBranch* branch = tree->GetBranch(BranchTypeToBranchEntryInfoBranchName(branchType).c_str());
00024 return branch;
00025 }
00026 }
00027 RootTree::RootTree(boost::shared_ptr<InputFile> filePtr,
00028 BranchType const& branchType,
00029 unsigned int maxVirtualSize,
00030 unsigned int cacheSize,
00031 unsigned int learningEntries) :
00032 filePtr_(filePtr),
00033 tree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr_->Get(BranchTypeToProductTreeName(branchType).c_str()) : 0)),
00034 metaTree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr_->Get(BranchTypeToMetaDataTreeName(branchType).c_str()) : 0)),
00035 branchType_(branchType),
00036 auxBranch_(tree_ ? getAuxiliaryBranch(tree_, branchType_) : 0),
00037 treeCache_(),
00038 rawTreeCache_(),
00039 entries_(tree_ ? tree_->GetEntries() : 0),
00040 entryNumber_(-1),
00041 branchNames_(),
00042 branches_(new BranchMap),
00043 trainNow_(false),
00044 switchOverEntry_(-1),
00045 learningEntries_(learningEntries),
00046 cacheSize_(cacheSize),
00047 rootDelayedReader_(new RootDelayedReader(*this, filePtr)),
00048 branchEntryInfoBranch_(metaTree_ ? getProductProvenanceBranch(metaTree_, branchType_) : (tree_ ? getProductProvenanceBranch(tree_, branchType_) : 0)),
00049 infoTree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToInfoTreeName(branchType).c_str()) : 0))
00050 {
00051 assert(tree_);
00052 setTreeMaxVirtualSize(maxVirtualSize);
00053 setCacheSize(cacheSize);
00054 }
00055
00056 RootTree::~RootTree() {
00057 }
00058
00059 bool
00060 RootTree::isValid() const {
00061 if (metaTree_ == 0 || metaTree_->GetNbranches() == 0) {
00062 return tree_ != 0 && auxBranch_ != 0;
00063 }
00064 if (tree_ != 0 && auxBranch_ != 0 && metaTree_ != 0) {
00065 if (branchEntryInfoBranch_ != 0 || infoTree_ != 0) return true;
00066 return (entries_ == metaTree_->GetEntries() && tree_->GetNbranches() <= metaTree_->GetNbranches() + 1);
00067 }
00068 return false;
00069 }
00070
00071 DelayedReader*
00072 RootTree::rootDelayedReader() const {
00073 rootDelayedReader_->reset();
00074 return rootDelayedReader_.get();
00075 }
00076
00077 void
00078 RootTree::setPresence(BranchDescription const& prod, std::string const& oldBranchName) {
00079 assert(isValid());
00080 prod.init();
00081 if(tree_->GetBranch(oldBranchName.c_str()) == 0){
00082 prod.setDropped();
00083 }
00084 }
00085
00086 void
00087 RootTree::addBranch(BranchKey const& key,
00088 BranchDescription const& prod,
00089 std::string const& oldBranchName) {
00090 assert(isValid());
00091 prod.init();
00092
00093 TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
00094 roottree::BranchInfo info = roottree::BranchInfo(ConstBranchDescription(prod));
00095 info.productBranch_ = 0;
00096 if (prod.present()) {
00097 info.productBranch_ = branch;
00098
00099 branchNames_.push_back(prod.branchName());
00100 }
00101 TTree* provTree = (metaTree_ != 0 ? metaTree_ : tree_);
00102 info.provenanceBranch_ = provTree->GetBranch(oldBranchName.c_str());
00103 branches_->insert(std::make_pair(key, info));
00104 }
00105
00106 void
00107 RootTree::dropBranch(std::string const& oldBranchName) {
00108
00109 TBranch* branch = tree_->GetBranch(oldBranchName.c_str());
00110 if (branch != 0) {
00111 TObjArray* leaves = tree_->GetListOfLeaves();
00112 int entries = leaves->GetEntries();
00113 for (int i = 0; i < entries; ++i) {
00114 TLeaf* leaf = (TLeaf*)(*leaves)[i];
00115 if (leaf == 0) continue;
00116 TBranch* br = leaf->GetBranch();
00117 if (br == 0) continue;
00118 if (br->GetMother() == branch) {
00119 leaves->Remove(leaf);
00120 }
00121 }
00122 leaves->Compress();
00123 tree_->GetListOfBranches()->Remove(branch);
00124 tree_->GetListOfBranches()->Compress();
00125 delete branch;
00126 }
00127 }
00128
00129 roottree::BranchMap const&
00130 RootTree::branches() const {return *branches_;}
00131
00132 void
00133 RootTree::setCacheSize(unsigned int cacheSize) {
00134 cacheSize_ = cacheSize;
00135 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize));
00136 treeCache_.reset(dynamic_cast<TTreeCache*>(filePtr_->GetCacheRead()));
00137 filePtr_->SetCacheRead(0);
00138 rawTreeCache_.reset();
00139 }
00140
00141 void
00142 RootTree::setTreeMaxVirtualSize(int treeMaxVirtualSize) {
00143 if (treeMaxVirtualSize >= 0) tree_->SetMaxVirtualSize(static_cast<Long64_t>(treeMaxVirtualSize));
00144 }
00145
00146 void
00147 RootTree::setEntryNumber(EntryNumber theEntryNumber) {
00148 filePtr_->SetCacheRead(treeCache_.get());
00149 entryNumber_ = theEntryNumber;
00150 tree_->LoadTree(entryNumber_);
00151 filePtr_->SetCacheRead(0);
00152 if(treeCache_ && trainNow_ && entryNumber_ >= 0) {
00153 startTraining();
00154 trainNow_ = false;
00155 }
00156 if (treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 && entryNumber_ >= switchOverEntry_) {
00157 stopTraining();
00158 }
00159 }
00160
00161 void
00162 RootTree::getEntry(TBranch* branch, EntryNumber entryNumber) const {
00163 try {
00164 if (!treeCache_) {
00165 filePtr_->SetCacheRead(0);
00166 branch->GetEntry(entryNumber);
00167 } else if (treeCache_->IsLearning() && rawTreeCache_) {
00168 treeCache_->AddBranch(branch, kTRUE);
00169 filePtr_->SetCacheRead(rawTreeCache_.get());
00170 branch->GetEntry(entryNumber);
00171 filePtr_->SetCacheRead(0);
00172 } else {
00173 filePtr_->SetCacheRead(treeCache_.get());
00174 branch->GetEntry(entryNumber);
00175 filePtr_->SetCacheRead(0);
00176 }
00177 } catch(cms::Exception const& e) {
00178
00179
00180 filePtr_->SetCacheRead(0);
00181 Exception t(errors::FileReadError, "", e);
00182 t.addContext(std::string("Reading branch ")+branch->GetName());
00183 throw t;
00184 }
00185 }
00186
00187 void
00188 RootTree::startTraining() {
00189 if (cacheSize_ == 0) {
00190 return;
00191 }
00192 assert(treeCache_ && treeCache_->GetOwner() == tree_);
00193 assert(branchType_ == InEvent);
00194 assert(!rawTreeCache_);
00195 treeCache_->SetLearnEntries(learningEntries_);
00196 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize_));
00197 rawTreeCache_.reset(dynamic_cast<TTreeCache *>(filePtr_->GetCacheRead()));
00198 filePtr_->SetCacheRead(0);
00199 rawTreeCache_->SetLearnEntries(0);
00200 switchOverEntry_ = entryNumber_ + learningEntries_;
00201 rawTreeCache_->StartLearningPhase();
00202 rawTreeCache_->SetEntryRange(entryNumber_, switchOverEntry_);
00203 rawTreeCache_->AddBranch("*", kTRUE);
00204 rawTreeCache_->StopLearningPhase();
00205 treeCache_->StartLearningPhase();
00206 treeCache_->SetEntryRange(switchOverEntry_, tree_->GetEntries());
00207 treeCache_->AddBranch(poolNames::branchListIndexesBranchName().c_str(), kTRUE);
00208 treeCache_->AddBranch(BranchTypeToAuxiliaryBranchName(branchType_).c_str(), kTRUE);
00209 }
00210
00211 void
00212 RootTree::stopTraining() {
00213 filePtr_->SetCacheRead(treeCache_.get());
00214 treeCache_->StopLearningPhase();
00215 rawTreeCache_.reset();
00216 }
00217
00218 void
00219 RootTree::close () {
00220
00221
00222 auxBranch_ = branchEntryInfoBranch_ = 0;
00223 tree_ = metaTree_ = infoTree_ = 0;
00224
00225
00226
00227 filePtr_->SetCacheRead(0);
00228
00229 filePtr_.reset();
00230 }
00231
00232 void
00233 RootTree::trainCache(char const* branchNames) {
00234 if (cacheSize_ == 0) {
00235 return;
00236 }
00237 tree_->LoadTree(0);
00238 assert(treeCache_);
00239 filePtr_->SetCacheRead(treeCache_.get());
00240 assert(treeCache_->GetOwner() == tree_);
00241 treeCache_->StartLearningPhase();
00242 treeCache_->SetEntryRange(0, tree_->GetEntries());
00243 treeCache_->AddBranch(branchNames, kTRUE);
00244 treeCache_->StopLearningPhase();
00245
00246
00247
00248 filePtr_->SetCacheRead(0);
00249 }
00250
00251 namespace roottree {
00252 Int_t
00253 getEntry(TBranch* branch, EntryNumber entryNumber) {
00254 Int_t n = 0;
00255 try {
00256 n = branch->GetEntry(entryNumber);
00257 }
00258 catch(cms::Exception const& e) {
00259 throw Exception(errors::FileReadError, "", e);
00260 }
00261 return n;
00262 }
00263
00264 Int_t
00265 getEntry(TTree* tree, EntryNumber entryNumber) {
00266 Int_t n = 0;
00267 try {
00268 n = tree->GetEntry(entryNumber);
00269 }
00270 catch(cms::Exception const& e) {
00271 throw Exception (errors::FileReadError, "", e);
00272 }
00273 return n;
00274 }
00275
00276 std::unique_ptr<TTreeCache>
00277 trainCache(TTree* tree, InputFile& file, unsigned int cacheSize, char const* branchNames) {
00278 tree->LoadTree(0);
00279 tree->SetCacheSize(cacheSize);
00280 std::unique_ptr<TTreeCache> treeCache(dynamic_cast<TTreeCache*>(file.GetCacheRead()));
00281 if (0 != treeCache.get()) {
00282 treeCache->StartLearningPhase();
00283 treeCache->SetEntryRange(0, tree->GetEntries());
00284 treeCache->AddBranch(branchNames, kTRUE);
00285 treeCache->StopLearningPhase();
00286 }
00287
00288
00289
00290 file.SetCacheRead(0);
00291 return treeCache;
00292 }
00293 }
00294 }