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