00001 #include "RootTree.h"
00002 #include "RootDelayedReader.h"
00003 #include "FWCore/Framework/interface/Principal.h"
00004 #include "FWCore/Utilities/interface/EDMException.h"
00005 #include "FWCore/Utilities/interface/Exception.h"
00006 #include "DataFormats/Provenance/interface/BranchDescription.h"
00007 #include "DataFormats/Provenance/interface/ConstBranchDescription.h"
00008 #include "InputFile.h"
00009 #include "TTree.h"
00010 #include "TTreeIndex.h"
00011 #include "TTreeCache.h"
00012
00013 #include <iostream>
00014
00015 namespace edm {
00016 namespace {
00017 TBranch* getAuxiliaryBranch(TTree* tree, BranchType const& branchType) {
00018 TBranch* branch = tree->GetBranch(BranchTypeToAuxiliaryBranchName(branchType).c_str());
00019 if (branch == 0) {
00020 branch = tree->GetBranch(BranchTypeToAuxBranchName(branchType).c_str());
00021 }
00022 return branch;
00023 }
00024 TBranch* getProductProvenanceBranch(TTree* tree, BranchType const& branchType) {
00025 TBranch* branch = tree->GetBranch(BranchTypeToBranchEntryInfoBranchName(branchType).c_str());
00026 return branch;
00027 }
00028 TBranch* getStatusBranch(TTree* tree, BranchType const& branchType) {
00029 TBranch* branch = tree->GetBranch(BranchTypeToProductStatusBranchName(branchType).c_str());
00030 return branch;
00031 }
00032 }
00033 RootTree::RootTree(boost::shared_ptr<InputFile> filePtr,
00034 BranchType const& branchType,
00035 unsigned int maxVirtualSize,
00036 unsigned int cacheSize,
00037 unsigned int learningEntries) :
00038 filePtr_(filePtr),
00039 tree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToProductTreeName(branchType).c_str()) : 0)),
00040 metaTree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToMetaDataTreeName(branchType).c_str()) : 0)),
00041 branchType_(branchType),
00042 auxBranch_(tree_ ? getAuxiliaryBranch(tree_, branchType_) : 0),
00043 branchEntryInfoBranch_(metaTree_ ? getProductProvenanceBranch(metaTree_, branchType_) : getProductProvenanceBranch(tree_, branchType_)),
00044 treeCache_(),
00045 rawTreeCache_(),
00046 entries_(tree_ ? tree_->GetEntries() : 0),
00047 entryNumber_(-1),
00048 branchNames_(),
00049 branches_(new BranchMap),
00050 trainNow_(false),
00051 switchOverEntry_(-1),
00052 learningEntries_(learningEntries),
00053 cacheSize_(cacheSize),
00054 productStatuses_(),
00055 pProductStatuses_(&productStatuses_),
00056 infoTree_(dynamic_cast<TTree*>(filePtr_.get() != 0 ? filePtr->Get(BranchTypeToInfoTreeName(branchType).c_str()) : 0)),
00057 statusBranch_(infoTree_ ? getStatusBranch(infoTree_, branchType_) : 0) {
00058 setTreeMaxVirtualSize(maxVirtualSize);
00059 setCacheSize(cacheSize);
00060 }
00061
00062 RootTree::~RootTree() {
00063 }
00064
00065 bool
00066 RootTree::isValid() const {
00067 if (metaTree_ == 0 || metaTree_->GetNbranches() == 0) {
00068 return tree_ != 0 && auxBranch_ != 0;
00069 }
00070 if (tree_ != 0 && auxBranch_ != 0 && metaTree_ != 0) {
00071 if (branchEntryInfoBranch_ != 0 || statusBranch_ != 0) return true;
00072 return (entries_ == metaTree_->GetEntries() && tree_->GetNbranches() <= metaTree_->GetNbranches() + 1);
00073 }
00074 return false;
00075 }
00076
00077 void
00078 RootTree::setPresence(BranchDescription const& prod) {
00079 assert(isValid());
00080 prod.init();
00081 if(tree_->GetBranch(prod.branchName().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 boost::shared_ptr<DelayedReader>
00133 RootTree::makeDelayedReader(FileFormatVersion const& fileFormatVersion, boost::shared_ptr<RootFile> rootFilePtr) const {
00134 boost::shared_ptr<DelayedReader>
00135 store(new RootDelayedReader(entryNumber_, branches_, *this, fileFormatVersion, rootFilePtr));
00136 return store;
00137 }
00138
00139 void
00140 RootTree::setCacheSize(unsigned int cacheSize) {
00141 cacheSize_ = cacheSize;
00142 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize));
00143 treeCache_.reset(dynamic_cast<TTreeCache*>(filePtr_->GetCacheRead()));
00144 filePtr_->SetCacheRead(0);
00145 rawTreeCache_.reset();
00146 }
00147
00148 void
00149 RootTree::setTreeMaxVirtualSize(int treeMaxVirtualSize) {
00150 if (treeMaxVirtualSize >= 0) tree_->SetMaxVirtualSize(static_cast<Long64_t>(treeMaxVirtualSize));
00151 }
00152
00153 void
00154 RootTree::setEntryNumber(EntryNumber theEntryNumber) {
00155 filePtr_->SetCacheRead(treeCache_.get());
00156 entryNumber_ = theEntryNumber;
00157 tree_->LoadTree(entryNumber_);
00158 filePtr_->SetCacheRead(0);
00159 if(treeCache_ && trainNow_ && entryNumber_ >= 0) {
00160 startTraining();
00161 trainNow_ = false;
00162 }
00163 if (treeCache_ && treeCache_->IsLearning() && switchOverEntry_ >= 0 && entryNumber_ >= switchOverEntry_) {
00164 stopTraining();
00165 }
00166 }
00167
00168 void
00169 RootTree::getEntry(TBranch* branch, EntryNumber entryNumber) const {
00170 if (!treeCache_) {
00171 filePtr_->SetCacheRead(0);
00172 roottree::getEntry(branch, entryNumber);
00173 } else if (treeCache_->IsLearning() && rawTreeCache_) {
00174 treeCache_->AddBranch(branch, kTRUE);
00175 filePtr_->SetCacheRead(rawTreeCache_.get());
00176 roottree::getEntry(branch, entryNumber);
00177 filePtr_->SetCacheRead(0);
00178 } else {
00179 filePtr_->SetCacheRead(treeCache_.get());
00180 roottree::getEntry(branch, entryNumber);
00181 filePtr_->SetCacheRead(0);
00182 }
00183 }
00184
00185 void
00186 RootTree::startTraining() {
00187 if (cacheSize_ == 0) {
00188 return;
00189 }
00190 assert(treeCache_ && treeCache_->GetOwner() == tree_);
00191 assert(branchType_ == InEvent);
00192 assert(!rawTreeCache_);
00193 treeCache_->SetLearnEntries(learningEntries_);
00194 tree_->SetCacheSize(static_cast<Long64_t>(cacheSize_));
00195 rawTreeCache_.reset(dynamic_cast<TTreeCache *>(filePtr_->GetCacheRead()));
00196 filePtr_->SetCacheRead(0);
00197 rawTreeCache_->SetLearnEntries(0);
00198 switchOverEntry_ = entryNumber_ + learningEntries_;
00199 rawTreeCache_->StartLearningPhase();
00200 rawTreeCache_->SetEntryRange(entryNumber_, switchOverEntry_);
00201 rawTreeCache_->AddBranch("*", kTRUE);
00202 rawTreeCache_->StopLearningPhase();
00203 treeCache_->StartLearningPhase();
00204 treeCache_->SetEntryRange(switchOverEntry_, tree_->GetEntries());
00205 treeCache_->AddBranch(poolNames::branchListIndexesBranchName().c_str(), kTRUE);
00206 treeCache_->AddBranch(BranchTypeToAuxiliaryBranchName(branchType_).c_str(), kTRUE);
00207 }
00208
00209 void
00210 RootTree::stopTraining() {
00211 filePtr_->SetCacheRead(treeCache_.get());
00212 treeCache_->StopLearningPhase();
00213 rawTreeCache_.reset();
00214 }
00215
00216 void
00217 RootTree::close () {
00218
00219
00220 auxBranch_ = branchEntryInfoBranch_ = statusBranch_ = 0;
00221 tree_ = metaTree_ = infoTree_ = 0;
00222
00223
00224
00225 filePtr_->SetCacheRead(0);
00226
00227 filePtr_.reset();
00228 }
00229
00230 void
00231 RootTree::trainCache(char const* branchNames) {
00232 if (cacheSize_ == 0) {
00233 return;
00234 }
00235 tree_->LoadTree(0);
00236 assert(treeCache_);
00237 filePtr_->SetCacheRead(treeCache_.get());
00238 assert(treeCache_->GetOwner() == tree_);
00239 treeCache_->StartLearningPhase();
00240 treeCache_->SetEntryRange(0, tree_->GetEntries());
00241 treeCache_->AddBranch(branchNames, kTRUE);
00242 treeCache_->StopLearningPhase();
00243
00244
00245
00246 filePtr_->SetCacheRead(0);
00247 }
00248
00249 namespace roottree {
00250 Int_t
00251 getEntry(TBranch* branch, EntryNumber entryNumber) {
00252 Int_t n = 0;
00253 try {
00254 n = branch->GetEntry(entryNumber);
00255 }
00256 catch(cms::Exception const& e) {
00257 throw Exception(errors::FileReadError) << e.explainSelf() << "\n";
00258 }
00259 return n;
00260 }
00261
00262 Int_t
00263 getEntry(TTree* tree, EntryNumber entryNumber) {
00264 Int_t n = 0;
00265 try {
00266 n = tree->GetEntry(entryNumber);
00267 }
00268 catch(cms::Exception const& e) {
00269 throw Exception(errors::FileReadError) << e.explainSelf() << "\n";
00270 }
00271 return n;
00272 }
00273
00274 std::auto_ptr<TTreeCache>
00275 trainCache(TTree* tree, InputFile& file, unsigned int cacheSize, char const* branchNames) {
00276 tree->LoadTree(0);
00277 tree->SetCacheSize(cacheSize);
00278 std::auto_ptr<TTreeCache> treeCache(dynamic_cast<TTreeCache*>(file.GetCacheRead()));
00279 if (0 != treeCache.get()) {
00280 treeCache->StartLearningPhase();
00281 treeCache->SetEntryRange(0, tree->GetEntries());
00282 treeCache->AddBranch(branchNames, kTRUE);
00283 treeCache->StopLearningPhase();
00284 }
00285
00286
00287
00288 file.SetCacheRead(0);
00289 return treeCache;
00290 }
00291 }
00292 }