00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "TChainIndex.h"
00019 #include "TChain.h"
00020 #include "TTreeFormula.h"
00021 #include "TTreeIndex.h"
00022 #include "TFile.h"
00023 #include "TError.h"
00024
00025 ClassImp(TChainIndex)
00026
00027
00028 TChainIndex::TChainIndex(): TVirtualIndex()
00029 {
00030
00031
00032 fTree = 0;
00033 fMajorFormulaParent = fMinorFormulaParent = 0;
00034 }
00035
00036
00037 TChainIndex::TChainIndex(const TTree *T, const char *majorname, const char *minorname)
00038 : TVirtualIndex()
00039 {
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 fTree = 0;
00050 fMajorFormulaParent = fMinorFormulaParent = 0;
00051
00052 TChain *chain = dynamic_cast<TChain*>(const_cast<TTree*>(T));
00053 if (!chain) {
00054 MakeZombie();
00055 Error("TChainIndex", "Cannot create a TChainIndex."
00056 " The Tree passed as an argument is not a TChain");
00057 return;
00058 }
00059
00060 fTree = (TTree*)T;
00061 fMajorName = majorname;
00062 fMinorName = minorname;
00063 Int_t i = 0;
00064
00065
00066 for (i = 0; i < chain->GetNtrees(); i++) {
00067 chain->LoadTree((chain->GetTreeOffset())[i]);
00068 TVirtualIndex *index = chain->GetTree()->GetTreeIndex();
00069
00070 TChainIndexEntry entry;
00071 entry.fTreeIndex = 0;
00072
00073
00074
00075 if (index) {
00076 if (strcmp(majorname,index->GetMajorName()) || strcmp(minorname,index->GetMinorName())) {
00077 MakeZombie();
00078 Error("TChainIndex","Tree in file %s has an index built with majorname=%s and minorname=%s",chain->GetTree()->GetCurrentFile()->GetName(),index->GetMajorName(),index->GetMinorName());
00079 return;
00080 }
00081 }
00082 if (!index) {
00083 chain->GetTree()->BuildIndex(majorname, minorname);
00084 index = chain->GetTree()->GetTreeIndex();
00085 chain->GetTree()->SetTreeIndex(0);
00086 entry.fTreeIndex = index;
00087 }
00088 if (!index || index->IsZombie() || index->GetN() == 0) {
00089 DeleteIndices();
00090 MakeZombie();
00091 Error("TChainIndex", "Error creating a tree index on a tree in the chain");
00092 return;
00093 }
00094
00095 TTreeIndex *ti_index = dynamic_cast<TTreeIndex*>(index);
00096 if (ti_index == 0) {
00097 Error("TChainIndex", "The underlying TTree must have a TTreeIndex but has a %s.",
00098 index->IsA()->GetName());
00099 return;
00100 }
00101
00102 entry.fMinIndexValue = ti_index->GetIndexValues()[0];
00103 entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
00104 fEntries.push_back(entry);
00105 }
00106
00107
00108 for (i = 0; i < Int_t(fEntries.size() - 1); i++) {
00109 if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
00110 DeleteIndices();
00111 MakeZombie();
00112 Error("TChainIndex", "The indices in files of this chain aren't sorted.");
00113 }
00114 }
00115
00116 }
00117
00118
00119 void TChainIndex::Append(const TVirtualIndex *index, Bool_t delaySort )
00120 {
00121
00122
00123 if (index) {
00124 const TTreeIndex *ti_index = dynamic_cast<const TTreeIndex*>(index);
00125 if (ti_index == 0) {
00126 Error("Append", "The given index is not a TTreeIndex but a %s",
00127 index->IsA()->GetName());
00128 }
00129
00130 TChainIndexEntry entry;
00131 entry.fTreeIndex = 0;
00132 entry.fMinIndexValue = ti_index->GetIndexValues()[0];
00133 entry.fMaxIndexValue = ti_index->GetIndexValues()[index->GetN() - 1];
00134 fEntries.push_back(entry);
00135 }
00136
00137 if (!delaySort) {
00138
00139 for (Int_t i = 0; i < Int_t(fEntries.size() - 1); i++) {
00140 if (fEntries[i].fMaxIndexValue > fEntries[i+1].fMinIndexValue) {
00141 DeleteIndices();
00142 MakeZombie();
00143 Error("Append", "The indices in files of this chain aren't sorted.");
00144 }
00145 }
00146 }
00147 }
00148
00149
00150 void TChainIndex::DeleteIndices()
00151 {
00152
00153 for (unsigned int i = 0; i < fEntries.size(); i++) {
00154 if (fEntries[i].fTreeIndex) {
00155 if (fTree->GetTree() && fTree->GetTree()->GetTreeIndex() == fEntries[i].fTreeIndex) {
00156 fTree->GetTree()->SetTreeIndex(0);
00157 SafeDelete(fEntries[i].fTreeIndex);
00158 }
00159 SafeDelete(fEntries[i].fTreeIndex);
00160 }
00161 }
00162 }
00163
00164
00165 TChainIndex::~TChainIndex()
00166 {
00167
00168 DeleteIndices();
00169 if (fTree && fTree->GetTreeIndex() == this)
00170 fTree->SetTreeIndex(0);
00171 }
00172
00173
00174 std::pair<TVirtualIndex*, Int_t> TChainIndex::GetSubTreeIndex(Int_t major, Int_t minor) const
00175 {
00176
00177
00178
00179
00180
00181 using namespace std;
00182 if (fEntries.size() == 0) {
00183 Warning("GetSubTreeIndex", "No subindices in the chain. The chain is probably empty");
00184 return make_pair(static_cast<TVirtualIndex*>(0), 0);
00185 }
00186
00187 Long64_t indexValue = (Long64_t(major) << 31) + minor;
00188
00189 if (indexValue < fEntries[0].fMinIndexValue) {
00190 Warning("GetSubTreeIndex", "The index value is less than the smallest index values in subtrees");
00191 return make_pair(static_cast<TVirtualIndex*>(0), 0);
00192 }
00193
00194 Int_t treeNo = fEntries.size() - 1;
00195 for (unsigned int i = 0; i < fEntries.size() - 1; i++) {
00196 if (indexValue < fEntries[i+1].fMinIndexValue) {
00197 treeNo = i;
00198 break;
00199 }
00200 }
00201 TChain* chain = dynamic_cast<TChain*> (fTree);
00202 R__ASSERT(chain);
00203 chain->LoadTree(chain->GetTreeOffset()[treeNo]);
00204 TVirtualIndex* index = fTree->GetTree()->GetTreeIndex();
00205 if (index)
00206 return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
00207 else {
00208 index = fEntries[treeNo].fTreeIndex;
00209 if (!index) {
00210 Warning("GetSubTreeIndex", "The tree has no index and the chain index"
00211 " doesn't store an index for that tree");
00212 return make_pair(static_cast<TVirtualIndex*>(0), 0);
00213 }
00214 else {
00215 fTree->GetTree()->SetTreeIndex(index);
00216 return make_pair(static_cast<TVirtualIndex*>(index), treeNo);
00217 }
00218 }
00219 }
00220
00221
00222 void TChainIndex::ReleaseSubTreeIndex(TVirtualIndex* index, int treeNo) const
00223 {
00224
00225
00226
00227
00228 if (fEntries[treeNo].fTreeIndex == index) {
00229 R__ASSERT(fTree->GetTree()->GetTreeIndex() == index);
00230 fTree->GetTree()->SetTreeIndex(0);
00231 }
00232 }
00233
00234
00235 Int_t TChainIndex::GetEntryNumberFriend(const TTree *T)
00236 {
00237
00238
00239 if (!T) return -3;
00240 GetMajorFormulaParent(T);
00241 GetMinorFormulaParent(T);
00242 if (!fMajorFormulaParent || !fMinorFormulaParent) return -1;
00243 if (!fMajorFormulaParent->GetNdim() || !fMinorFormulaParent->GetNdim()) {
00244
00245
00246
00247 Int_t pentry = T->GetReadEntry();
00248 if (pentry >= (Int_t)fTree->GetEntries()) return -2;
00249
00250
00251 return pentry;
00252 }
00253
00254
00255
00256 Double_t majord = fMajorFormulaParent->EvalInstance();
00257 Double_t minord = fMinorFormulaParent->EvalInstance();
00258 Long64_t majorv = (Long64_t)majord;
00259 Long64_t minorv = (Long64_t)minord;
00260
00261
00262
00263 return fTree->GetEntryNumberWithIndex(majorv,minorv);
00264 }
00265
00266
00267 Long64_t TChainIndex::GetEntryNumberWithBestIndex(Int_t major, Int_t minor) const
00268 {
00269
00270
00271 std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
00272 if (!indexAndNumber.first) {
00273 Error("GetEntryNumberWithBestIndex","no index found");
00274 return -1;
00275 }
00276 else {
00277 Long64_t rv = indexAndNumber.first->GetEntryNumberWithBestIndex(major, minor);
00278 ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
00279 TChain* chain = dynamic_cast<TChain*> (fTree);
00280 R__ASSERT(chain);
00281 return rv + chain->GetTreeOffset()[indexAndNumber.second];
00282 }
00283 }
00284
00285
00286 Long64_t TChainIndex::GetEntryNumberWithIndex(Int_t major, Int_t minor) const
00287 {
00288
00289
00290
00291 std::pair<TVirtualIndex*, Int_t> indexAndNumber = GetSubTreeIndex(major, minor);
00292 if (!indexAndNumber.first) {
00293 Error("GetEntryNumberWithIndex","no index found");
00294 return -1;
00295 }
00296 else {
00297 Long64_t rv = indexAndNumber.first->GetEntryNumberWithIndex(major, minor);
00298 ReleaseSubTreeIndex(indexAndNumber.first, indexAndNumber.second);
00299 TChain* chain = dynamic_cast<TChain*> (fTree);
00300 R__ASSERT(chain);
00301 return rv + chain->GetTreeOffset()[indexAndNumber.second];
00302 }
00303 }
00304
00305
00306 TTreeFormula *TChainIndex::GetMajorFormulaParent(const TTree *T)
00307 {
00308
00309
00310 if (!fMajorFormulaParent) {
00311 fMajorFormulaParent = new TTreeFormula("MajorP",fMajorName.Data(),(TTree*)T);
00312 fMajorFormulaParent->SetQuickLoad(kTRUE);
00313 }
00314 if (fMajorFormulaParent->GetTree() != T) {
00315 fMajorFormulaParent->SetTree((TTree*)T);
00316 fMajorFormulaParent->UpdateFormulaLeaves();
00317 }
00318 return fMajorFormulaParent;
00319 }
00320
00321
00322 TTreeFormula *TChainIndex::GetMinorFormulaParent(const TTree *T)
00323 {
00324
00325
00326 if (!fMinorFormulaParent) {
00327 fMinorFormulaParent = new TTreeFormula("MinorP",fMinorName.Data(),(TTree*)T);
00328 fMinorFormulaParent->SetQuickLoad(kTRUE);
00329 }
00330 if (fMinorFormulaParent->GetTree() != T) {
00331 fMinorFormulaParent->SetTree((TTree*)T);
00332 fMinorFormulaParent->UpdateFormulaLeaves();
00333 }
00334
00335 return fMinorFormulaParent;
00336 }
00337
00338
00339 void TChainIndex::UpdateFormulaLeaves(const TTree *parent)
00340 {
00341
00342
00343 if (fMajorFormulaParent) {
00344 if (parent) fMajorFormulaParent->SetTree((TTree*)parent);
00345 fMajorFormulaParent->UpdateFormulaLeaves();
00346 }
00347 if (fMinorFormulaParent) {
00348 if (parent) fMinorFormulaParent->SetTree((TTree*)parent);
00349 fMinorFormulaParent->UpdateFormulaLeaves();
00350 }
00351 }
00352
00353
00354 void TChainIndex::SetTree(const TTree *T)
00355 {
00356
00357
00358 R__ASSERT(fTree == 0 || fTree == T || T==0);
00359 }
00360